/** * On-disk MCP server config — the `mcpServers` array that ACP clients * usually pass over the wire, but loaded straight from JSON so direct CLI * users (and our VS Code extension) don't have to roll their own config UI. * * Lookup precedence: * 1. `/.codeep/mcp_servers.json` (project — committed with repo) * 2. `~/.codeep/mcp_servers.json` (global — user's machine) * Project entries shadow global entries with the same server name. * * File format mirrors what Claude Code accepts so existing user configs can * be reused verbatim: * * { * "mcpServers": { * "fs": { * "command": "npx", * "args": ["@modelcontextprotocol/server-filesystem", "/some/path"], * "env": { "READ_ONLY": "1" } * }, * "gh": { ... } * } * } * * A flat array form (`{"mcpServers": [{...}, ...]}`) is also accepted because * that's the shape ACP passes over JSON-RPC. */ import type { McpServer } from '../acp/protocol.js'; export interface McpConfigFile { /** Either the named-map form (Claude Code style) or a flat array (ACP style). */ mcpServers?: Record> | McpServer[]; } /** * Load MCP server definitions for a workspace. Project entries shadow * global entries with the same server name. Workspace-less calls * (TUI without project) return only the global config. * * Sources read (highest precedence first on name collisions): * 1. /.codeep/mcp_servers.json (Codeep-native project file) * 2. /.mcp.json (cross-tool standard — same * shape Claude Code/Cursor/Kilo Code read, so users can keep one MCP * config for their whole fleet) * 3. ~/.codeep/mcp_servers.json (global — user's machine) */ export declare function loadMcpServerConfig(workspaceRoot?: string): McpServer[]; /** * Same sources as `loadMcpServerConfig`, but split by trust domain: * `global` (~/.codeep — the user's own machine-wide file) vs `workspace` * (files that arrive WITH a repo: `.codeep/mcp_servers.json` + `.mcp.json`). * * Workspace entries are attacker-controllable — anyone who clones a repo * containing one of these files would otherwise spawn arbitrary commands * at startup — so callers must gate them behind `isWorkspaceMcpTrusted` * before spawning (mirrors the `trustedHookProjects` gate for hooks). * On name collisions a workspace entry shadows a global one, matching * the merged loader's precedence. */ export declare function loadMcpServerConfigSplit(workspaceRoot?: string): { global: McpServer[]; workspace: McpServer[]; }; export declare function isWorkspaceMcpTrusted(workspaceRoot: string): boolean; export declare function trustWorkspaceMcp(workspaceRoot: string): void; export declare function untrustWorkspaceMcp(workspaceRoot: string): void; /** * Merge two server lists: ACP-provided + on-disk. ACP wins on collisions * — the client knows its own config, so a Zed-passed server overrides a * project file entry of the same name (and we never have to teach Zed to * "skip" file-based ones). */ export declare function mergeMcpServers(fromConfig: McpServer[], fromAcp: McpServer[] | undefined): McpServer[]; /** * The MCP servers a session runs. Every place that (re)starts a session's * servers goes through here, so they all apply the same rule: * * - global (~/.codeep) entries always run — they are the user's own — * unless a workspace entry of the same name runs in their place; * - workspace entries run only once the workspace is trusted, because * they arrive with the repo. `userAdded` names entries the user has * just added by hand (`/mcp add`, `/mcp install`); those need no * further consent; * - `fromClient` — the servers the editor passed for the session — run * too and win on name collisions, as in `mergeMcpServers`. * * `skipped` lists the workspace entries left out, so callers can say why. * Registering replaces a session's whole set of servers, which is why the * editor's servers have to be part of every selection. */ export declare function selectSessionMcpServers(workspaceRoot: string | undefined, opts?: { fromClient?: McpServer[]; userAdded?: string[]; }): { servers: McpServer[]; skipped: McpServer[]; }; /** * Add or replace a server entry in the project config file. Used by the * interactive `/mcp add` command. Project file is created if missing. */ export declare function addProjectMcpServer(workspaceRoot: string, server: McpServer): void; /** * Remove a server entry from the project config file. Returns true if a * server with that name was actually removed. */ export declare function removeProjectMcpServer(workspaceRoot: string, name: string): boolean;