mcpsmgr 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1631 -0
- package/dist/index.js.map +1 -0
- package/docs/README_zh-CN.md +99 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/design.md +41 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/proposal.md +28 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/specs/project-operations/spec.md +53 -0
- package/openspec/changes/archive/2026-03-12-fix-global-mcp-default-selection/tasks.md +9 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/design.md +40 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/proposal.md +25 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/specs/project-operations/spec.md +25 -0
- package/openspec/changes/archive/2026-03-12-fix-init-server-detection/tasks.md +10 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/design.md +32 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/proposal.md +25 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/specs/project-operations/spec.md +30 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/specs/server-management/spec.md +15 -0
- package/openspec/changes/archive/2026-03-12-graceful-exit-on-interrupt/tasks.md +17 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/design.md +104 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/proposal.md +34 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/agent-adapters/spec.md +110 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/central-storage/spec.md +38 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/glm-integration/spec.md +66 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/project-operations/spec.md +76 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/specs/server-management/spec.md +75 -0
- package/openspec/changes/archive/2026-03-12-mcps-manager-cli/tasks.md +60 -0
- package/openspec/config.yaml +20 -0
- package/openspec/specs/agent-adapters/spec.md +148 -0
- package/openspec/specs/central-storage/spec.md +42 -0
- package/openspec/specs/glm-integration/spec.md +70 -0
- package/openspec/specs/project-operations/spec.md +138 -0
- package/openspec/specs/server-management/spec.md +93 -0
- package/package.json +33 -0
- package/src/__tests__/integration.test.ts +200 -0
- package/src/adapters/__tests__/adapters.test.ts +274 -0
- package/src/adapters/antigravity.ts +114 -0
- package/src/adapters/claude-code.ts +114 -0
- package/src/adapters/codex-cli.ts +135 -0
- package/src/adapters/env-args.ts +51 -0
- package/src/adapters/gemini-cli.ts +110 -0
- package/src/adapters/index.ts +32 -0
- package/src/adapters/json-file.ts +24 -0
- package/src/adapters/opencode.ts +114 -0
- package/src/commands/add.ts +68 -0
- package/src/commands/init.ts +136 -0
- package/src/commands/list.ts +77 -0
- package/src/commands/remove.ts +61 -0
- package/src/commands/server-add.ts +211 -0
- package/src/commands/server-list.ts +24 -0
- package/src/commands/server-remove.ts +12 -0
- package/src/commands/setup.ts +71 -0
- package/src/commands/sync.ts +98 -0
- package/src/index.ts +100 -0
- package/src/services/glm-client.ts +190 -0
- package/src/services/system-prompt.ts +61 -0
- package/src/services/web-reader.ts +130 -0
- package/src/types.ts +59 -0
- package/src/utils/config.ts +22 -0
- package/src/utils/paths.ts +11 -0
- package/src/utils/prompt.ts +3 -0
- package/src/utils/resolve-config.ts +13 -0
- package/src/utils/server-store.ts +56 -0
- package/tsconfig.json +17 -0
- package/tsup.config.ts +13 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/config.ts","../src/utils/paths.ts","../src/commands/setup.ts","../src/utils/prompt.ts","../src/commands/server-add.ts","../src/utils/server-store.ts","../src/services/web-reader.ts","../src/services/system-prompt.ts","../src/services/glm-client.ts","../src/commands/server-remove.ts","../src/commands/server-list.ts","../src/commands/init.ts","../src/adapters/index.ts","../src/adapters/claude-code.ts","../src/adapters/json-file.ts","../src/adapters/env-args.ts","../src/adapters/codex-cli.ts","../src/adapters/gemini-cli.ts","../src/adapters/opencode.ts","../src/adapters/antigravity.ts","../src/utils/resolve-config.ts","../src/commands/add.ts","../src/commands/remove.ts","../src/commands/sync.ts","../src/commands/list.ts"],"sourcesContent":["import { program } from \"commander\";\nimport { configExists } from \"./utils/config.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { serverAddCommand } from \"./commands/server-add.js\";\nimport { serverRemoveCommand } from \"./commands/server-remove.js\";\nimport { serverListCommand } from \"./commands/server-list.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { addCommand } from \"./commands/add.js\";\nimport { removeCommand } from \"./commands/remove.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { listCommand } from \"./commands/list.js\";\n\nfunction requireSetup(): void {\n if (!configExists()) {\n console.error(\n 'mcpsmgr is not configured. Run \"mcpsmgr setup\" first.',\n );\n process.exit(1);\n }\n}\n\nprogram\n .name(\"mcpsmgr\")\n .description(\"Unified MCP server manager for multiple coding agents\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"setup\")\n .description(\"Initialize mcpsmgr configuration\")\n .action(setupCommand);\n\nconst server = program\n .command(\"server\")\n .description(\"Manage MCP server definitions in central repository\");\n\nserver\n .command(\"add [source]\")\n .description(\"Add an MCP server (URL or GitHub owner/repo)\")\n .action((source?: string) => {\n requireSetup();\n return serverAddCommand(source);\n });\n\nserver\n .command(\"remove <name>\")\n .description(\"Remove an MCP server from central repository\")\n .action((name: string) => {\n requireSetup();\n return serverRemoveCommand(name);\n });\n\nserver\n .command(\"list\")\n .description(\"List all servers in central repository\")\n .action(() => {\n requireSetup();\n return serverListCommand();\n });\n\nprogram\n .command(\"init\")\n .description(\"Initialize MCP servers for current project\")\n .action(() => {\n requireSetup();\n return initCommand();\n });\n\nprogram\n .command(\"add <server-name>\")\n .description(\"Add a server from central repository to current project\")\n .action((serverName: string) => {\n requireSetup();\n return addCommand(serverName);\n });\n\nprogram\n .command(\"remove <server-name>\")\n .description(\"Remove a server from current project agent configs\")\n .action((serverName: string) => {\n requireSetup();\n return removeCommand(serverName);\n });\n\nprogram\n .command(\"sync\")\n .description(\"Sync central repository changes to project agent configs\")\n .action(() => {\n requireSetup();\n return syncCommand();\n });\n\nprogram\n .command(\"list\")\n .description(\"List MCP servers across all agent configs in current project\")\n .action(() => {\n requireSetup();\n return listCommand();\n });\n\nprogram.parse();\n","import { readFile, writeFile, mkdir, chmod } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport type { GlobalConfig } from \"../types.js\";\nimport { paths } from \"./paths.js\";\n\nexport async function readGlobalConfig(): Promise<GlobalConfig> {\n const raw = await readFile(paths.configFile, \"utf-8\");\n return JSON.parse(raw) as GlobalConfig;\n}\n\nexport async function writeGlobalConfig(config: GlobalConfig): Promise<void> {\n if (!existsSync(paths.baseDir)) {\n await mkdir(paths.baseDir, { recursive: true });\n await chmod(paths.baseDir, 0o700);\n }\n await writeFile(paths.configFile, JSON.stringify(config, null, 2), \"utf-8\");\n await chmod(paths.configFile, 0o600);\n}\n\nexport function configExists(): boolean {\n return existsSync(paths.configFile);\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst BASE_DIR = join(homedir(), \".mcps-manager\");\n\nexport const paths = {\n baseDir: BASE_DIR,\n serversDir: join(BASE_DIR, \"servers\"),\n configFile: join(BASE_DIR, \"config.json\"),\n serverFile: (name: string): string => join(BASE_DIR, \"servers\", `${name}.json`),\n} as const;\n","import { mkdir, chmod } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { input, select, confirm } from \"@inquirer/prompts\";\nimport type { GlobalConfig } from \"../types.js\";\nimport { paths } from \"../utils/paths.js\";\nimport { writeGlobalConfig, configExists } from \"../utils/config.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\n\nconst GLM_ENDPOINTS = [\n {\n name: \"Coding Plan (GLM-5)\",\n value: \"https://open.bigmodel.cn/api/coding/paas/v4/chat/completions\",\n },\n {\n name: \"General (GLM-5)\",\n value: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n },\n] as const;\n\nexport async function setupCommand(): Promise<void> {\n try {\n await setupCommandInner();\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function setupCommandInner(): Promise<void> {\n if (configExists()) {\n const overwrite = await confirm({\n message: \"Configuration already exists. Overwrite?\",\n });\n if (!overwrite) {\n console.log(\"Setup cancelled.\");\n return;\n }\n }\n\n if (!existsSync(paths.baseDir)) {\n await mkdir(paths.baseDir, { recursive: true });\n await chmod(paths.baseDir, 0o700);\n }\n if (!existsSync(paths.serversDir)) {\n await mkdir(paths.serversDir, { recursive: true });\n }\n\n const glmApiKey = await input({\n message: \"Enter GLM5 API Key:\",\n validate: (v) => (v.trim().length > 0 ? true : \"API key is required\"),\n });\n\n const glmEndpoint = await select({\n message: \"Select GLM5 endpoint:\",\n choices: GLM_ENDPOINTS.map((e) => ({ name: e.name, value: e.value })),\n });\n\n const config: GlobalConfig = {\n glm: {\n apiKey: glmApiKey.trim(),\n endpoint: glmEndpoint,\n },\n webReader: {\n apiKey: glmApiKey.trim(),\n url: \"https://open.bigmodel.cn/api/mcp/web_reader/mcp\",\n },\n };\n\n await writeGlobalConfig(config);\n console.log(\"Setup complete. Configuration saved to ~/.mcps-manager/config.json\");\n}\n","export function isUserCancellation(error: unknown): boolean {\n return error instanceof Error && error.name === \"ExitPromptError\";\n}\n","import { confirm, input, password } from \"@inquirer/prompts\";\nimport type { DefaultConfig, ServerDefinition, StdioConfig } from \"../types.js\";\nimport { readGlobalConfig } from \"../utils/config.js\";\nimport {\n serverExists,\n writeServerDefinition,\n} from \"../utils/server-store.js\";\nimport {\n isValidInput,\n buildUserMessage,\n analyzeWithGlm,\n type AnalysisResult,\n} from \"../services/glm-client.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\n\nexport async function serverAddCommand(source?: string): Promise<void> {\n try {\n await serverAddCommandInner(source);\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function serverAddCommandInner(source?: string): Promise<void> {\n const urlInput =\n source ??\n (await input({\n message: \"Enter MCP server URL or GitHub owner/repo (leave empty for manual):\",\n }));\n\n if (urlInput.trim() === \"\") {\n await manualAddFlow();\n return;\n }\n\n const validation = isValidInput(urlInput.trim());\n if (!validation.valid) {\n console.error(`Error: ${validation.reason}`);\n process.exitCode = 1;\n return;\n }\n\n const config = await readGlobalConfig();\n\n console.log(\"Analyzing documentation with GLM5...\");\n let analysis: AnalysisResult;\n try {\n const userMessage = buildUserMessage(urlInput.trim());\n analysis = await analyzeWithGlm(config, userMessage);\n } catch (error) {\n console.error(\n `GLM5 analysis failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n const fallback = await confirm({\n message: \"Would you like to configure manually instead?\",\n });\n if (fallback) {\n await manualAddFlow();\n }\n return;\n }\n\n displayAnalysisResult(analysis, urlInput.trim());\n\n const trust = await confirm({\n message: \"Trust this analysis result?\",\n });\n\n if (!trust) {\n const manual = await confirm({\n message: \"Configure manually instead?\",\n });\n if (manual) {\n await manualAddFlow();\n }\n return;\n }\n\n if (serverExists(analysis.name)) {\n console.error(\n `Error: Server \"${analysis.name}\" already exists. Run \"mcpsmgr server remove ${analysis.name}\" first.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const env: Record<string, string> = {};\n for (const varName of analysis.requiredEnvVars) {\n const value = await password({\n message: `Enter value for ${varName} (stored locally, never sent to servers):`,\n mask: \"*\",\n });\n env[varName] = value;\n }\n\n const defaultConfig: DefaultConfig =\n analysis.default.transport === \"stdio\"\n ? {\n transport: \"stdio\",\n command: analysis.default.command ?? \"\",\n args: [...(analysis.default.args ?? [])],\n env: { ...(analysis.default.env ?? {}), ...env },\n }\n : {\n transport: \"http\",\n url: analysis.default.url ?? \"\",\n headers: { ...(analysis.default.headers ?? {}) },\n };\n\n const definition: ServerDefinition = {\n name: analysis.name,\n source: urlInput.trim(),\n default: defaultConfig,\n overrides: analysis.overrides as ServerDefinition[\"overrides\"],\n };\n\n await writeServerDefinition(definition);\n console.log(`Server \"${analysis.name}\" saved to central repository.`);\n}\n\nfunction displayAnalysisResult(result: AnalysisResult, source: string): void {\n console.log(\"\\n--- Analysis Result ---\");\n console.log(`Name: ${result.name}`);\n console.log(`Source: ${source}`);\n console.log(`Transport: ${result.default.transport}`);\n if (result.default.transport === \"stdio\") {\n console.log(`Command: ${result.default.command}`);\n console.log(`Args: ${JSON.stringify(result.default.args)}`);\n } else {\n console.log(`URL: ${result.default.url}`);\n }\n if (Object.keys(result.overrides).length > 0) {\n console.log(\"Agent overrides:\");\n for (const [agent, override] of Object.entries(result.overrides)) {\n console.log(` ${agent}: ${JSON.stringify(override)}`);\n }\n }\n if (result.requiredEnvVars.length > 0) {\n console.log(\n `Required env vars: ${result.requiredEnvVars.join(\", \")}`,\n );\n }\n console.log(\"---\\n\");\n}\n\nasync function manualAddFlow(): Promise<void> {\n const name = await input({\n message: \"Server name (kebab-case):\",\n validate: (v) =>\n /^[a-z][a-z0-9-]*$/.test(v.trim()) ? true : \"Must be kebab-case\",\n });\n\n if (serverExists(name.trim())) {\n console.error(\n `Error: Server \"${name.trim()}\" already exists. Run \"mcpsmgr server remove ${name.trim()}\" first.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const source = await input({\n message: \"Source URL (optional):\",\n });\n\n const command = await input({\n message: \"Command (e.g., npx):\",\n validate: (v) => (v.trim().length > 0 ? true : \"Command is required\"),\n });\n\n const argsStr = await input({\n message: \"Args (comma-separated, e.g., -y,@scope/package):\",\n });\n const args = argsStr\n .trim()\n .split(\",\")\n .map((a) => a.trim())\n .filter((a) => a.length > 0);\n\n const envPairs: Record<string, string> = {};\n let addMore = true;\n while (addMore) {\n const envName = await input({\n message: \"Env var name (leave empty to finish):\",\n });\n if (envName.trim() === \"\") break;\n const envValue = await password({\n message: `Value for ${envName.trim()} (stored locally, never sent to servers):`,\n mask: \"*\",\n });\n envPairs[envName.trim()] = envValue;\n addMore = true;\n }\n\n const config: StdioConfig = {\n transport: \"stdio\",\n command: command.trim(),\n args,\n env: envPairs,\n };\n\n const definition: ServerDefinition = {\n name: name.trim(),\n source: source.trim(),\n default: config,\n overrides: {},\n };\n\n await writeServerDefinition(definition);\n console.log(`Server \"${name.trim()}\" saved to central repository.`);\n}\n","import { readFile, writeFile, readdir, unlink, mkdir, chmod } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport type { ServerDefinition } from \"../types.js\";\nimport { paths } from \"./paths.js\";\n\nexport async function readServerDefinition(\n name: string,\n): Promise<ServerDefinition | undefined> {\n const filePath = paths.serverFile(name);\n if (!existsSync(filePath)) {\n return undefined;\n }\n const raw = await readFile(filePath, \"utf-8\");\n return JSON.parse(raw) as ServerDefinition;\n}\n\nexport async function writeServerDefinition(\n definition: ServerDefinition,\n): Promise<void> {\n if (!existsSync(paths.serversDir)) {\n await mkdir(paths.serversDir, { recursive: true });\n }\n const filePath = paths.serverFile(definition.name);\n await writeFile(filePath, JSON.stringify(definition, null, 2), \"utf-8\");\n await chmod(filePath, 0o600);\n}\n\nexport async function removeServerDefinition(name: string): Promise<boolean> {\n const filePath = paths.serverFile(name);\n if (!existsSync(filePath)) {\n return false;\n }\n await unlink(filePath);\n return true;\n}\n\nexport async function listServerDefinitions(): Promise<ServerDefinition[]> {\n if (!existsSync(paths.serversDir)) {\n return [];\n }\n const files = await readdir(paths.serversDir);\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n const results: ServerDefinition[] = [];\n for (const file of jsonFiles) {\n const raw = await readFile(\n paths.serverFile(file.replace(\".json\", \"\")),\n \"utf-8\",\n );\n results.push(JSON.parse(raw) as ServerDefinition);\n }\n return results;\n}\n\nexport function serverExists(name: string): boolean {\n return existsSync(paths.serverFile(name));\n}\n","import type { GlobalConfig } from \"../types.js\";\n\ninterface McpResponse {\n readonly jsonrpc: string;\n readonly id: number;\n readonly result?: {\n readonly content?: readonly { readonly type: string; readonly text: string }[];\n readonly isError?: boolean;\n };\n readonly error?: { readonly code: number; readonly message: string };\n}\n\nfunction parseSseResponse(raw: string): McpResponse {\n const lines = raw.split(\"\\n\");\n for (const line of lines) {\n if (line.startsWith(\"data:\")) {\n return JSON.parse(line.slice(5)) as McpResponse;\n }\n }\n return JSON.parse(raw) as McpResponse;\n}\n\nasync function mcpInitialize(\n endpoint: string,\n apiKey: string,\n): Promise<string> {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"initialize\",\n params: {\n protocolVersion: \"2025-03-26\",\n capabilities: {},\n clientInfo: { name: \"mcpsmgr\", version: \"0.1.0\" },\n },\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `MCP initialize failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const sessionId = response.headers.get(\"mcp-session-id\");\n if (!sessionId) {\n throw new Error(\"MCP server did not return session ID\");\n }\n\n return sessionId;\n}\n\nasync function mcpToolCall(\n endpoint: string,\n apiKey: string,\n sessionId: string,\n toolName: string,\n args: Record<string, unknown>,\n): Promise<string> {\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n Authorization: `Bearer ${apiKey}`,\n \"Mcp-Session-Id\": sessionId,\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 2,\n method: \"tools/call\",\n params: { name: toolName, arguments: args },\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `MCP tools/call failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const raw = await response.text();\n const parsed = parseSseResponse(raw);\n\n if (parsed.error) {\n throw new Error(`MCP error: ${parsed.error.message}`);\n }\n\n const contents = parsed.result?.content ?? [];\n const full = contents.map((c) => c.text).join(\"\\n\");\n const MAX_CONTENT_LENGTH = 30000;\n if (full.length > MAX_CONTENT_LENGTH) {\n return full.slice(0, MAX_CONTENT_LENGTH) + \"\\n\\n[Content truncated]\";\n }\n return full;\n}\n\nlet cachedSessionId: string | undefined;\n\nexport async function fetchWebContent(\n config: GlobalConfig,\n url: string,\n): Promise<string> {\n const endpoint = config.webReader.url;\n const apiKey = config.webReader.apiKey;\n\n if (!cachedSessionId) {\n cachedSessionId = await mcpInitialize(endpoint, apiKey);\n }\n\n try {\n return await mcpToolCall(endpoint, apiKey, cachedSessionId, \"webReader\", {\n url,\n timeout: 20,\n });\n } catch {\n cachedSessionId = await mcpInitialize(endpoint, apiKey);\n return await mcpToolCall(endpoint, apiKey, cachedSessionId, \"webReader\", {\n url,\n timeout: 20,\n });\n }\n}\n","export const ANALYSIS_SYSTEM_PROMPT = `You are an MCP (Model Context Protocol) server configuration analyst. Your task is to analyze documentation for an MCP server and extract configuration details for 5 different coding agents.\n\nThe 5 agents and their configuration differences:\n\n1. **Claude Code** (.mcp.json)\n - Format: { \"type\": \"stdio\"|\"http\", \"command\": \"...\", \"args\": [...] }\n - HTTP: { \"type\": \"http\", \"url\": \"...\", \"headers\": {...} }\n - IMPORTANT: Do NOT use \"env\" field. Environment variables will be handled separately.\n\n2. **Codex CLI** (.codex/config.toml)\n - TOML format: command = \"...\", args = [...]\n - Same key names as Claude Code but in TOML\n - IMPORTANT: Do NOT use \"env\" field.\n\n3. **Gemini CLI** (.gemini/settings.json)\n - Format: { \"command\": \"...\", \"args\": [...] }\n - No \"type\" field needed\n - IMPORTANT: Do NOT use \"env\" field.\n\n4. **OpenCode** (opencode.json)\n - Format: { \"type\": \"local\"|\"remote\", \"command\": [\"cmd\", \"arg1\", ...] }\n - command is an ARRAY including the command itself\n - type is \"local\" for stdio, \"remote\" for http\n - IMPORTANT: Do NOT use \"environment\" field.\n\n5. **Antigravity** (~/.gemini/antigravity/mcp_config.json)\n - Format: { \"command\": \"...\", \"args\": [...] }\n - HTTP: { \"serverUrl\": \"...\", \"headers\": {...} } (note: \"serverUrl\" not \"url\")\n - IMPORTANT: Do NOT use \"env\" field.\n\nYou have access to a webReader tool to fetch web page content. Use it to read the documentation URL provided.\n\nAfter analyzing the documentation, return a JSON object with this exact structure:\n\\`\\`\\`json\n{\n \"name\": \"server-name\",\n \"default\": {\n \"transport\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@scope/package\"],\n },\n \"overrides\": {\n \"opencode\": {\n \"transport\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@scope/package\"],\n \"env\": {}\n }\n },\n \"requiredEnvVars\": [\"API_KEY\"]\n}\n\\`\\`\\`\n\nRules:\n- \"name\" should be a kebab-case identifier for the server\n- \"default\" should be the most common configuration (usually works for Claude Code, Codex CLI, Gemini CLI)\n- Only add \"overrides\" for agents that need DIFFERENT configuration from the default\n- OpenCode usually needs an override because its command format differs (array vs string+args)\n- \"requiredEnvVars\" lists environment variable names the user needs to provide values for\n- Transport is either \"stdio\" or \"http\"\n- Return ONLY the JSON object, no markdown fences, no explanation`;\n","import type { GlobalConfig } from \"../types.js\";\nimport { fetchWebContent } from \"./web-reader.js\";\nimport { ANALYSIS_SYSTEM_PROMPT } from \"./system-prompt.js\";\n\ninterface GlmMessage {\n readonly role: \"system\" | \"user\" | \"assistant\" | \"tool\";\n readonly content: string | null;\n readonly tool_calls?: readonly GlmToolCall[];\n readonly tool_call_id?: string;\n}\n\ninterface GlmToolCall {\n readonly id: string;\n readonly type: \"function\";\n readonly function: {\n readonly name: string;\n readonly arguments: string;\n };\n}\n\ninterface GlmResponse {\n readonly choices: readonly {\n readonly message: GlmMessage;\n readonly finish_reason: string;\n }[];\n}\n\nconst WEB_READER_TOOL = {\n type: \"function\" as const,\n function: {\n name: \"webReader\",\n description: \"Fetch and read the content of a web page given its URL\",\n parameters: {\n type: \"object\",\n properties: {\n url: {\n type: \"string\",\n description: \"The URL of the web page to read\",\n },\n },\n required: [\"url\"],\n },\n },\n};\n\nexport interface AnalysisResult {\n readonly name: string;\n readonly default: {\n readonly transport: \"stdio\" | \"http\";\n readonly command?: string;\n readonly args?: readonly string[];\n readonly env?: Readonly<Record<string, string>>;\n readonly url?: string;\n readonly headers?: Readonly<Record<string, string>>;\n };\n readonly overrides: Readonly<Record<string, unknown>>;\n readonly requiredEnvVars: readonly string[];\n}\n\nasync function callGlm(\n config: GlobalConfig,\n messages: GlmMessage[],\n): Promise<GlmResponse> {\n const response = await fetch(config.glm.endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${config.glm.apiKey}`,\n },\n body: JSON.stringify({\n model: \"glm-5\",\n messages,\n tools: [WEB_READER_TOOL],\n tool_choice: \"auto\",\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n `GLM5 API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n return (await response.json()) as GlmResponse;\n}\n\nexport async function analyzeWithGlm(\n config: GlobalConfig,\n userMessage: string,\n): Promise<AnalysisResult> {\n const messages: GlmMessage[] = [\n { role: \"system\", content: ANALYSIS_SYSTEM_PROMPT },\n { role: \"user\", content: userMessage },\n ];\n\n const MAX_ROUNDS = 10;\n for (let round = 0; round < MAX_ROUNDS; round++) {\n const response = await callGlm(config, messages);\n const choice = response.choices.at(0);\n if (!choice) {\n throw new Error(\"GLM5 returned empty response\");\n }\n\n const assistantMessage = choice.message;\n messages.push({\n role: \"assistant\",\n content: assistantMessage.content,\n tool_calls: assistantMessage.tool_calls,\n });\n\n if (\n !assistantMessage.tool_calls ||\n assistantMessage.tool_calls.length === 0\n ) {\n return parseAnalysisResult(assistantMessage.content ?? \"\");\n }\n\n for (const toolCall of assistantMessage.tool_calls) {\n if (toolCall.function.name === \"webReader\") {\n const args = JSON.parse(toolCall.function.arguments) as {\n url: string;\n };\n let toolResult: string;\n try {\n toolResult = await fetchWebContent(config, args.url);\n } catch (error) {\n toolResult = `Error fetching URL: ${error instanceof Error ? error.message : String(error)}`;\n }\n messages.push({\n role: \"tool\",\n content: toolResult,\n tool_call_id: toolCall.id,\n });\n }\n }\n }\n\n throw new Error(\"GLM5 analysis exceeded maximum rounds\");\n}\n\nfunction parseAnalysisResult(content: string): AnalysisResult {\n const cleaned = content\n .replace(/```json\\s*/g, \"\")\n .replace(/```\\s*/g, \"\")\n .trim();\n\n const jsonMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n throw new Error(`Cannot extract JSON from GLM5 response: ${cleaned.slice(0, 200)}`);\n }\n\n const result = JSON.parse(jsonMatch[0]) as AnalysisResult;\n if (!result.name || !result.default) {\n throw new Error(\"Invalid analysis result: missing name or default config\");\n }\n\n return result;\n}\n\nexport function buildUserMessage(input: string): string {\n if (isGitHubRepo(input)) {\n const url = `https://github.com/${input}`;\n return `Please analyze the MCP server at ${url}. Start by reading the README at ${url}/blob/main/README.md`;\n }\n return `Please analyze the MCP server documentation at: ${input}`;\n}\n\nexport function isGitHubRepo(input: string): boolean {\n if (input.startsWith(\"http\") || input.startsWith(\"@\")) {\n return false;\n }\n const parts = input.split(\"/\");\n return parts.length === 2 && parts.every((p) => p.length > 0);\n}\n\nexport function isValidInput(\n input: string,\n): { valid: true } | { valid: false; reason: string } {\n if (input.startsWith(\"http://\") || input.startsWith(\"https://\")) {\n return { valid: true };\n }\n if (isGitHubRepo(input)) {\n return { valid: true };\n }\n return {\n valid: false,\n reason:\n 'Invalid input format. Provide a URL (https://...) or GitHub owner/repo (e.g., \"anthropics/mcp-brave-search\")',\n };\n}\n","import { removeServerDefinition, serverExists } from \"../utils/server-store.js\";\n\nexport async function serverRemoveCommand(name: string): Promise<void> {\n if (!serverExists(name)) {\n console.error(`Error: Server \"${name}\" does not exist in central repository.`);\n process.exitCode = 1;\n return;\n }\n\n await removeServerDefinition(name);\n console.log(`Server \"${name}\" removed from central repository.`);\n}\n","import { listServerDefinitions } from \"../utils/server-store.js\";\n\nexport async function serverListCommand(): Promise<void> {\n const servers = await listServerDefinitions();\n\n if (servers.length === 0) {\n console.log(\"No servers in central repository. Use \\\"mcpsmgr server add\\\" to add one.\");\n return;\n }\n\n console.log(\"\\nCentral Repository Servers:\\n\");\n for (const server of servers) {\n const overrideCount = Object.keys(server.overrides).length;\n const overrideInfo =\n overrideCount > 0 ? ` (${overrideCount} overrides)` : \"\";\n console.log(\n ` ${server.name} [${server.default.transport}]${overrideInfo}`,\n );\n if (server.source) {\n console.log(` source: ${server.source}`);\n }\n }\n console.log();\n}\n","import { checkbox, confirm } from \"@inquirer/prompts\";\nimport { allAdapters, detectAgents } from \"../adapters/index.js\";\nimport { listServerDefinitions } from \"../utils/server-store.js\";\nimport { resolveConfig } from \"../utils/resolve-config.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\nimport type { AgentAdapter } from \"../types.js\";\n\nexport async function initCommand(): Promise<void> {\n try {\n await initCommandInner();\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function initCommandInner(): Promise<void> {\n const projectDir = process.cwd();\n\n const servers = await listServerDefinitions();\n if (servers.length === 0) {\n console.log(\n \"Central repository is empty. Use \\\"mcpsmgr server add\\\" to add servers first.\",\n );\n return;\n }\n\n const detected = detectAgents(projectDir);\n const detectedIds = new Set(detected.map((a) => a.id));\n\n const selectedAgents = await checkbox<AgentAdapter>({\n message: \"Select agents to configure:\",\n choices: allAdapters.map((adapter) => ({\n name: `${adapter.name}${detectedIds.has(adapter.id) ? \" (detected)\" : \"\"}${adapter.isGlobal ? \" [global]\" : \"\"}`,\n value: adapter,\n checked: detectedIds.has(adapter.id) && !adapter.isGlobal,\n })),\n });\n\n if (selectedAgents.length === 0) {\n console.log(\"No agents selected.\");\n return;\n }\n\n const agentServerMap = new Map<string, Set<string>>();\n const detectedServers = new Set<string>();\n for (const agent of selectedAgents) {\n try {\n const existing = await agent.read(projectDir);\n const names = new Set(Object.keys(existing));\n agentServerMap.set(agent.id, names);\n for (const name of names) {\n detectedServers.add(name);\n }\n } catch {\n // silent fallback per design decision\n }\n }\n\n const selectedServers = await checkbox({\n message: \"Select servers to deploy:\",\n choices: servers.map((s) => ({\n name: `${s.name}${detectedServers.has(s.name) ? \" (detected)\" : \"\"} [${s.default.transport}]`,\n value: s,\n checked: detectedServers.has(s.name),\n })),\n });\n\n const selectedServerNames = new Set(selectedServers.map((s) => s.name));\n\n const removals = new Map<string, AgentAdapter[]>();\n for (const serverName of detectedServers) {\n if (!selectedServerNames.has(serverName)) {\n const agents = selectedAgents.filter((a) => {\n const agentServers = agentServerMap.get(a.id);\n return agentServers?.has(serverName);\n });\n if (agents.length > 0) {\n removals.set(serverName, agents);\n }\n }\n }\n\n if (selectedServers.length === 0 && removals.size === 0) {\n console.log(\"No servers selected.\");\n return;\n }\n\n console.log(\"\\nPlan:\");\n for (const agent of selectedAgents) {\n console.log(` ${agent.name}:`);\n for (const server of selectedServers) {\n console.log(` + ${server.name}`);\n }\n for (const [serverName, agents] of removals) {\n if (agents.some((a) => a.id === agent.id)) {\n console.log(` - ${serverName}`);\n }\n }\n }\n\n const proceed = await confirm({ message: \"Proceed?\" });\n if (!proceed) {\n console.log(\"Cancelled.\");\n return;\n }\n\n for (const agent of selectedAgents) {\n for (const server of selectedServers) {\n try {\n const config = resolveConfig(server, agent);\n await agent.write(projectDir, server.name, config);\n console.log(` + ${server.name} -> ${agent.name}`);\n } catch (error) {\n console.warn(\n ` ! ${server.name} -> ${agent.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n for (const [serverName, agents] of removals) {\n for (const agent of agents) {\n try {\n await agent.remove(projectDir, serverName);\n console.log(` - ${serverName} <- ${agent.name}`);\n } catch (error) {\n console.warn(\n ` ! ${serverName} <- ${agent.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n console.log(\"\\nDone.\");\n}\n","import { existsSync } from \"node:fs\";\nimport type { AgentAdapter, AgentId } from \"../types.js\";\nimport { claudeCodeAdapter } from \"./claude-code.js\";\nimport { codexCliAdapter } from \"./codex-cli.js\";\nimport { geminiCliAdapter } from \"./gemini-cli.js\";\nimport { opencodeAdapter } from \"./opencode.js\";\nimport { antigravityAdapter } from \"./antigravity.js\";\n\nexport const allAdapters: readonly AgentAdapter[] = [\n claudeCodeAdapter,\n codexCliAdapter,\n geminiCliAdapter,\n opencodeAdapter,\n antigravityAdapter,\n];\n\nexport function getAdapter(id: AgentId): AgentAdapter {\n const adapter = allAdapters.find((a) => a.id === id);\n if (!adapter) {\n throw new Error(`Unknown agent: ${id}`);\n }\n return adapter;\n}\n\nexport function detectAgents(projectDir: string): AgentAdapter[] {\n return allAdapters.filter((adapter) => {\n if (adapter.isGlobal) {\n return existsSync(adapter.configPath(projectDir));\n }\n return existsSync(adapter.configPath(projectDir));\n });\n}\n","import { join } from \"node:path\";\nimport type { AgentAdapter, DefaultConfig } from \"../types.js\";\nimport { readJsonFile, writeJsonFile } from \"./json-file.js\";\nimport { buildEnvArgs, parseEnvArgs, resolveEnvInArgs } from \"./env-args.js\";\n\nfunction toAgentFormat(config: DefaultConfig): Record<string, unknown> {\n if (config.transport === \"stdio\") {\n const { resolvedArgs, remainingEnv } = resolveEnvInArgs(\n config.args,\n config.env,\n );\n const envArgs = buildEnvArgs(remainingEnv);\n if (envArgs.length > 0) {\n return {\n type: \"stdio\",\n command: \"env\",\n args: [...envArgs, config.command, ...resolvedArgs],\n };\n }\n return {\n type: \"stdio\",\n command: config.command,\n args: resolvedArgs,\n };\n }\n return {\n type: \"http\",\n url: config.url,\n headers: { ...config.headers },\n };\n}\n\nfunction fromAgentFormat(\n _name: string,\n raw: Record<string, unknown>,\n): DefaultConfig | undefined {\n const type = raw[\"type\"] as string | undefined;\n if (type === \"stdio\") {\n const command = raw[\"command\"] as string;\n const rawArgs = (raw[\"args\"] as string[]) ?? [];\n const legacyEnv = raw[\"env\"] as Record<string, string> | undefined;\n\n if (legacyEnv && Object.keys(legacyEnv).length > 0) {\n return { transport: \"stdio\", command, args: rawArgs, env: legacyEnv };\n }\n\n if (command === \"env\") {\n const { env, commandIndex } = parseEnvArgs(rawArgs);\n return {\n transport: \"stdio\",\n command: rawArgs[commandIndex] ?? \"\",\n args: rawArgs.slice(commandIndex + 1),\n env,\n };\n }\n\n return { transport: \"stdio\", command, args: rawArgs, env: {} };\n }\n if (type === \"http\") {\n return {\n transport: \"http\",\n url: raw[\"url\"] as string,\n headers: (raw[\"headers\"] as Record<string, string>) ?? {},\n };\n }\n return undefined;\n}\n\nexport const claudeCodeAdapter: AgentAdapter = {\n id: \"claude-code\",\n name: \"Claude Code\",\n configPath: (projectDir) => join(projectDir, \".mcp.json\"),\n isGlobal: false,\n\n toAgentFormat,\n fromAgentFormat,\n\n async read(projectDir) {\n const filePath = join(projectDir, \".mcp.json\");\n const data = await readJsonFile(filePath);\n return (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n },\n\n async write(projectDir, serverName, config) {\n const filePath = join(projectDir, \".mcp.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n if (serverName in servers) {\n throw new Error(\n `Conflict: \"${serverName}\" already exists in Claude Code config`,\n );\n }\n const updated = {\n ...data,\n mcpServers: { ...servers, [serverName]: toAgentFormat(config) },\n };\n await writeJsonFile(filePath, updated);\n },\n\n async remove(projectDir, serverName) {\n const filePath = join(projectDir, \".mcp.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n const { [serverName]: _, ...rest } = servers;\n await writeJsonFile(filePath, { ...data, mcpServers: rest });\n },\n\n async has(projectDir, serverName) {\n const filePath = join(projectDir, \".mcp.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n return serverName in servers;\n },\n};\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nexport async function readJsonFile(\n filePath: string,\n): Promise<Record<string, unknown>> {\n if (!existsSync(filePath)) {\n return {};\n }\n const raw = await readFile(filePath, \"utf-8\");\n return JSON.parse(raw) as Record<string, unknown>;\n}\n\nexport async function writeJsonFile(\n filePath: string,\n data: Record<string, unknown>,\n): Promise<void> {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, JSON.stringify(data, null, 2) + \"\\n\", \"utf-8\");\n}\n","const ENV_VAR_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*=/;\n\nexport function buildEnvArgs(\n env: Readonly<Record<string, string>>,\n): string[] {\n return Object.entries(env).map(([key, value]) => `${key}=${value}`);\n}\n\nexport function parseEnvArgs(args: readonly string[]): {\n readonly env: Record<string, string>;\n readonly commandIndex: number;\n} {\n const env: Record<string, string> = {};\n for (let i = 0; i < args.length; i++) {\n if (ENV_VAR_PATTERN.test(args[i])) {\n const eqIndex = args[i].indexOf(\"=\");\n env[args[i].slice(0, eqIndex)] = args[i].slice(eqIndex + 1);\n } else {\n return { env, commandIndex: i };\n }\n }\n return { env, commandIndex: args.length };\n}\n\nexport function resolveEnvInArgs(\n args: readonly string[],\n env: Readonly<Record<string, string>>,\n): {\n readonly resolvedArgs: string[];\n readonly remainingEnv: Record<string, string>;\n} {\n const substitutedKeys = new Set<string>();\n const resolvedArgs = args.map((arg) =>\n arg.replace(/\\$\\{([^}]+)\\}/g, (match, varName: string) => {\n if (varName in env) {\n substitutedKeys.add(varName);\n return env[varName];\n }\n return match;\n }),\n );\n\n const remainingEnv: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (!substitutedKeys.has(key)) {\n remainingEnv[key] = value;\n }\n }\n\n return { resolvedArgs, remainingEnv };\n}\n","import { join } from \"node:path\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport type { AgentAdapter, DefaultConfig } from \"../types.js\";\nimport { buildEnvArgs, parseEnvArgs, resolveEnvInArgs } from \"./env-args.js\";\n\nfunction toAgentFormat(config: DefaultConfig): Record<string, unknown> {\n if (config.transport === \"stdio\") {\n const { resolvedArgs, remainingEnv } = resolveEnvInArgs(\n config.args,\n config.env,\n );\n const envArgs = buildEnvArgs(remainingEnv);\n if (envArgs.length > 0) {\n return {\n command: \"env\",\n args: [...envArgs, config.command, ...resolvedArgs],\n };\n }\n return {\n command: config.command,\n args: resolvedArgs,\n };\n }\n return {\n url: config.url,\n headers: { ...config.headers },\n };\n}\n\nfunction fromAgentFormat(\n _name: string,\n raw: Record<string, unknown>,\n): DefaultConfig | undefined {\n if (raw[\"command\"]) {\n const command = raw[\"command\"] as string;\n const rawArgs = (raw[\"args\"] as string[]) ?? [];\n const legacyEnv = raw[\"env\"] as Record<string, string> | undefined;\n\n if (legacyEnv && Object.keys(legacyEnv).length > 0) {\n return { transport: \"stdio\", command, args: rawArgs, env: legacyEnv };\n }\n\n if (command === \"env\") {\n const { env, commandIndex } = parseEnvArgs(rawArgs);\n return {\n transport: \"stdio\",\n command: rawArgs[commandIndex] ?? \"\",\n args: rawArgs.slice(commandIndex + 1),\n env,\n };\n }\n\n return { transport: \"stdio\", command, args: rawArgs, env: {} };\n }\n if (raw[\"url\"]) {\n return {\n transport: \"http\",\n url: raw[\"url\"] as string,\n headers: (raw[\"headers\"] as Record<string, string>) ?? {},\n };\n }\n return undefined;\n}\n\nasync function readTomlFile(\n filePath: string,\n): Promise<{ raw: string; parsed: Record<string, unknown> }> {\n if (!existsSync(filePath)) {\n return { raw: \"\", parsed: {} };\n }\n const raw = await readFile(filePath, \"utf-8\");\n const parsed = parseToml(raw) as Record<string, unknown>;\n return { raw, parsed };\n}\n\nasync function writeTomlFile(\n filePath: string,\n data: Record<string, unknown>,\n): Promise<void> {\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(filePath, stringifyToml(data) + \"\\n\", \"utf-8\");\n}\n\nexport const codexCliAdapter: AgentAdapter = {\n id: \"codex-cli\",\n name: \"Codex CLI\",\n configPath: (projectDir) => join(projectDir, \".codex\", \"config.toml\"),\n isGlobal: false,\n\n toAgentFormat,\n fromAgentFormat,\n\n async read(projectDir) {\n const filePath = join(projectDir, \".codex\", \"config.toml\");\n const { parsed } = await readTomlFile(filePath);\n return (parsed[\"mcp_servers\"] as Record<string, unknown>) ?? {};\n },\n\n async write(projectDir, serverName, config) {\n const filePath = join(projectDir, \".codex\", \"config.toml\");\n const { parsed } = await readTomlFile(filePath);\n const servers = (parsed[\"mcp_servers\"] as Record<string, unknown>) ?? {};\n if (serverName in servers) {\n throw new Error(\n `Conflict: \"${serverName}\" already exists in Codex CLI config`,\n );\n }\n const updated = {\n ...parsed,\n mcp_servers: { ...servers, [serverName]: toAgentFormat(config) },\n };\n await writeTomlFile(filePath, updated);\n },\n\n async remove(projectDir, serverName) {\n const filePath = join(projectDir, \".codex\", \"config.toml\");\n const { parsed } = await readTomlFile(filePath);\n const servers = (parsed[\"mcp_servers\"] as Record<string, unknown>) ?? {};\n const { [serverName]: _, ...rest } = servers;\n await writeTomlFile(filePath, { ...parsed, mcp_servers: rest });\n },\n\n async has(projectDir, serverName) {\n const filePath = join(projectDir, \".codex\", \"config.toml\");\n const { parsed } = await readTomlFile(filePath);\n const servers = (parsed[\"mcp_servers\"] as Record<string, unknown>) ?? {};\n return serverName in servers;\n },\n};\n","import { join } from \"node:path\";\nimport type { AgentAdapter, DefaultConfig } from \"../types.js\";\nimport { readJsonFile, writeJsonFile } from \"./json-file.js\";\nimport { buildEnvArgs, parseEnvArgs, resolveEnvInArgs } from \"./env-args.js\";\n\nfunction toAgentFormat(config: DefaultConfig): Record<string, unknown> {\n if (config.transport === \"stdio\") {\n const { resolvedArgs, remainingEnv } = resolveEnvInArgs(\n config.args,\n config.env,\n );\n const envArgs = buildEnvArgs(remainingEnv);\n if (envArgs.length > 0) {\n return {\n command: \"env\",\n args: [...envArgs, config.command, ...resolvedArgs],\n };\n }\n return {\n command: config.command,\n args: resolvedArgs,\n };\n }\n return {\n url: config.url,\n headers: { ...config.headers },\n };\n}\n\nfunction fromAgentFormat(\n _name: string,\n raw: Record<string, unknown>,\n): DefaultConfig | undefined {\n if (raw[\"command\"]) {\n const command = raw[\"command\"] as string;\n const rawArgs = (raw[\"args\"] as string[]) ?? [];\n const legacyEnv = raw[\"env\"] as Record<string, string> | undefined;\n\n if (legacyEnv && Object.keys(legacyEnv).length > 0) {\n return { transport: \"stdio\", command, args: rawArgs, env: legacyEnv };\n }\n\n if (command === \"env\") {\n const { env, commandIndex } = parseEnvArgs(rawArgs);\n return {\n transport: \"stdio\",\n command: rawArgs[commandIndex] ?? \"\",\n args: rawArgs.slice(commandIndex + 1),\n env,\n };\n }\n\n return { transport: \"stdio\", command, args: rawArgs, env: {} };\n }\n if (raw[\"url\"]) {\n return {\n transport: \"http\",\n url: raw[\"url\"] as string,\n headers: (raw[\"headers\"] as Record<string, string>) ?? {},\n };\n }\n return undefined;\n}\n\nexport const geminiCliAdapter: AgentAdapter = {\n id: \"gemini-cli\",\n name: \"Gemini CLI\",\n configPath: (projectDir) => join(projectDir, \".gemini\", \"settings.json\"),\n isGlobal: false,\n\n toAgentFormat,\n fromAgentFormat,\n\n async read(projectDir) {\n const filePath = join(projectDir, \".gemini\", \"settings.json\");\n const data = await readJsonFile(filePath);\n return (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n },\n\n async write(projectDir, serverName, config) {\n const filePath = join(projectDir, \".gemini\", \"settings.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n if (serverName in servers) {\n throw new Error(\n `Conflict: \"${serverName}\" already exists in Gemini CLI config`,\n );\n }\n const updated = {\n ...data,\n mcpServers: { ...servers, [serverName]: toAgentFormat(config) },\n };\n await writeJsonFile(filePath, updated);\n },\n\n async remove(projectDir, serverName) {\n const filePath = join(projectDir, \".gemini\", \"settings.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n const { [serverName]: _, ...rest } = servers;\n await writeJsonFile(filePath, { ...data, mcpServers: rest });\n },\n\n async has(projectDir, serverName) {\n const filePath = join(projectDir, \".gemini\", \"settings.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n return serverName in servers;\n },\n};\n","import { join } from \"node:path\";\nimport type { AgentAdapter, DefaultConfig } from \"../types.js\";\nimport { readJsonFile, writeJsonFile } from \"./json-file.js\";\nimport { buildEnvArgs, parseEnvArgs, resolveEnvInArgs } from \"./env-args.js\";\n\nfunction toAgentFormat(config: DefaultConfig): Record<string, unknown> {\n if (config.transport === \"stdio\") {\n const { resolvedArgs, remainingEnv } = resolveEnvInArgs(\n config.args,\n config.env,\n );\n const envArgs = buildEnvArgs(remainingEnv);\n if (envArgs.length > 0) {\n return {\n type: \"local\",\n command: [\"env\", ...envArgs, config.command, ...resolvedArgs],\n };\n }\n return {\n type: \"local\",\n command: [config.command, ...resolvedArgs],\n };\n }\n return {\n type: \"remote\",\n url: config.url,\n headers: { ...config.headers },\n };\n}\n\nfunction fromAgentFormat(\n _name: string,\n raw: Record<string, unknown>,\n): DefaultConfig | undefined {\n const type = raw[\"type\"] as string | undefined;\n if (type === \"local\") {\n const commandArr = raw[\"command\"] as string[];\n const legacyEnv = raw[\"environment\"] as Record<string, string> | undefined;\n\n if (legacyEnv && Object.keys(legacyEnv).length > 0) {\n const [command = \"\", ...args] = commandArr;\n return { transport: \"stdio\", command, args, env: legacyEnv };\n }\n\n if (commandArr[0] === \"env\") {\n const { env, commandIndex } = parseEnvArgs(commandArr.slice(1));\n const actualIndex = commandIndex + 1;\n return {\n transport: \"stdio\",\n command: commandArr[actualIndex] ?? \"\",\n args: commandArr.slice(actualIndex + 1),\n env,\n };\n }\n\n const [command = \"\", ...args] = commandArr;\n return { transport: \"stdio\", command, args, env: {} };\n }\n if (type === \"remote\") {\n return {\n transport: \"http\",\n url: raw[\"url\"] as string,\n headers: (raw[\"headers\"] as Record<string, string>) ?? {},\n };\n }\n return undefined;\n}\n\nexport const opencodeAdapter: AgentAdapter = {\n id: \"opencode\",\n name: \"OpenCode\",\n configPath: (projectDir) => join(projectDir, \"opencode.json\"),\n isGlobal: false,\n\n toAgentFormat,\n fromAgentFormat,\n\n async read(projectDir) {\n const filePath = join(projectDir, \"opencode.json\");\n const data = await readJsonFile(filePath);\n return (data[\"mcp\"] as Record<string, unknown>) ?? {};\n },\n\n async write(projectDir, serverName, config) {\n const filePath = join(projectDir, \"opencode.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcp\"] as Record<string, unknown>) ?? {};\n if (serverName in servers) {\n throw new Error(\n `Conflict: \"${serverName}\" already exists in OpenCode config`,\n );\n }\n const updated = {\n ...data,\n mcp: { ...servers, [serverName]: toAgentFormat(config) },\n };\n await writeJsonFile(filePath, updated);\n },\n\n async remove(projectDir, serverName) {\n const filePath = join(projectDir, \"opencode.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcp\"] as Record<string, unknown>) ?? {};\n const { [serverName]: _, ...rest } = servers;\n await writeJsonFile(filePath, { ...data, mcp: rest });\n },\n\n async has(projectDir, serverName) {\n const filePath = join(projectDir, \"opencode.json\");\n const data = await readJsonFile(filePath);\n const servers = (data[\"mcp\"] as Record<string, unknown>) ?? {};\n return serverName in servers;\n },\n};\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentAdapter, DefaultConfig } from \"../types.js\";\nimport { readJsonFile, writeJsonFile } from \"./json-file.js\";\nimport { buildEnvArgs, parseEnvArgs, resolveEnvInArgs } from \"./env-args.js\";\n\nconst GLOBAL_CONFIG_PATH = join(\n homedir(),\n \".gemini\",\n \"antigravity\",\n \"mcp_config.json\",\n);\n\nfunction toAgentFormat(config: DefaultConfig): Record<string, unknown> {\n if (config.transport === \"stdio\") {\n const { resolvedArgs, remainingEnv } = resolveEnvInArgs(\n config.args,\n config.env,\n );\n const envArgs = buildEnvArgs(remainingEnv);\n if (envArgs.length > 0) {\n return {\n command: \"env\",\n args: [...envArgs, config.command, ...resolvedArgs],\n };\n }\n return {\n command: config.command,\n args: resolvedArgs,\n };\n }\n return {\n serverUrl: config.url,\n headers: { ...config.headers },\n };\n}\n\nfunction fromAgentFormat(\n _name: string,\n raw: Record<string, unknown>,\n): DefaultConfig | undefined {\n if (raw[\"command\"]) {\n const command = raw[\"command\"] as string;\n const rawArgs = (raw[\"args\"] as string[]) ?? [];\n const legacyEnv = raw[\"env\"] as Record<string, string> | undefined;\n\n if (legacyEnv && Object.keys(legacyEnv).length > 0) {\n return { transport: \"stdio\", command, args: rawArgs, env: legacyEnv };\n }\n\n if (command === \"env\") {\n const { env, commandIndex } = parseEnvArgs(rawArgs);\n return {\n transport: \"stdio\",\n command: rawArgs[commandIndex] ?? \"\",\n args: rawArgs.slice(commandIndex + 1),\n env,\n };\n }\n\n return { transport: \"stdio\", command, args: rawArgs, env: {} };\n }\n if (raw[\"serverUrl\"]) {\n return {\n transport: \"http\",\n url: raw[\"serverUrl\"] as string,\n headers: (raw[\"headers\"] as Record<string, string>) ?? {},\n };\n }\n return undefined;\n}\n\nexport const antigravityAdapter: AgentAdapter = {\n id: \"antigravity\",\n name: \"Antigravity\",\n configPath: () => GLOBAL_CONFIG_PATH,\n isGlobal: true,\n\n toAgentFormat,\n fromAgentFormat,\n\n async read() {\n const data = await readJsonFile(GLOBAL_CONFIG_PATH);\n return (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n },\n\n async write(_projectDir, serverName, config) {\n const data = await readJsonFile(GLOBAL_CONFIG_PATH);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n if (serverName in servers) {\n throw new Error(\n `Conflict: \"${serverName}\" already exists in Antigravity config`,\n );\n }\n const updated = {\n ...data,\n mcpServers: { ...servers, [serverName]: toAgentFormat(config) },\n };\n await writeJsonFile(GLOBAL_CONFIG_PATH, updated);\n },\n\n async remove(_projectDir, serverName) {\n const data = await readJsonFile(GLOBAL_CONFIG_PATH);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n const { [serverName]: _, ...rest } = servers;\n await writeJsonFile(GLOBAL_CONFIG_PATH, { ...data, mcpServers: rest });\n },\n\n async has(_projectDir, serverName) {\n const data = await readJsonFile(GLOBAL_CONFIG_PATH);\n const servers = (data[\"mcpServers\"] as Record<string, unknown>) ?? {};\n return serverName in servers;\n },\n};\n","import type { AgentAdapter, DefaultConfig, ServerDefinition } from \"../types.js\";\n\nexport function resolveConfig(\n definition: ServerDefinition,\n adapter: AgentAdapter,\n): DefaultConfig {\n const override = definition.overrides[adapter.id];\n if (override) {\n const base = definition.default;\n return { ...base, ...override } as DefaultConfig;\n }\n return definition.default;\n}\n","import { checkbox } from \"@inquirer/prompts\";\nimport { detectAgents } from \"../adapters/index.js\";\nimport { readServerDefinition, serverExists } from \"../utils/server-store.js\";\nimport { resolveConfig } from \"../utils/resolve-config.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\nimport type { AgentAdapter } from \"../types.js\";\n\nexport async function addCommand(serverName: string): Promise<void> {\n try {\n await addCommandInner(serverName);\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function addCommandInner(serverName: string): Promise<void> {\n const projectDir = process.cwd();\n\n if (!serverExists(serverName)) {\n console.error(\n `Error: Server \"${serverName}\" not found in central repository.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const definition = await readServerDefinition(serverName);\n if (!definition) {\n console.error(`Error: Failed to read server definition for \"${serverName}\".`);\n process.exitCode = 1;\n return;\n }\n\n const detected = detectAgents(projectDir);\n if (detected.length === 0) {\n console.log(\n \"No agent config files detected in this project. Use \\\"mcpsmgr init\\\" first.\",\n );\n return;\n }\n\n const selectedAgents = await checkbox<AgentAdapter>({\n message: `Select agents to add \"${serverName}\" to:`,\n choices: detected.map((adapter) => ({\n name: `${adapter.name}${adapter.isGlobal ? \" [global]\" : \"\"}`,\n value: adapter,\n checked: !adapter.isGlobal,\n })),\n });\n\n if (selectedAgents.length === 0) {\n console.log(\"No agents selected.\");\n return;\n }\n\n for (const agent of selectedAgents) {\n try {\n const config = resolveConfig(definition, agent);\n await agent.write(projectDir, serverName, config);\n console.log(` + ${serverName} -> ${agent.name}`);\n } catch (error) {\n console.warn(\n ` ! ${serverName} -> ${agent.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n","import { checkbox } from \"@inquirer/prompts\";\nimport { allAdapters } from \"../adapters/index.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\nimport type { AgentAdapter } from \"../types.js\";\n\nexport async function removeCommand(serverName: string): Promise<void> {\n try {\n await removeCommandInner(serverName);\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function removeCommandInner(serverName: string): Promise<void> {\n const projectDir = process.cwd();\n\n const agentsWithServer: AgentAdapter[] = [];\n for (const adapter of allAdapters) {\n try {\n const has = await adapter.has(projectDir, serverName);\n if (has) {\n agentsWithServer.push(adapter);\n }\n } catch {\n // config file doesn't exist, skip\n }\n }\n\n if (agentsWithServer.length === 0) {\n console.log(\n `Server \"${serverName}\" not found in any agent configuration.`,\n );\n return;\n }\n\n const selectedAgents = await checkbox<AgentAdapter>({\n message: `Remove \"${serverName}\" from which agents?`,\n choices: agentsWithServer.map((adapter) => ({\n name: `${adapter.name}${adapter.isGlobal ? \" [global]\" : \"\"}`,\n value: adapter,\n checked: !adapter.isGlobal,\n })),\n });\n\n if (selectedAgents.length === 0) {\n console.log(\"No agents selected.\");\n return;\n }\n\n for (const agent of selectedAgents) {\n try {\n await agent.remove(projectDir, serverName);\n console.log(` - ${serverName} <- ${agent.name}`);\n } catch (error) {\n console.warn(\n ` ! ${serverName} <- ${agent.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n","import { confirm } from \"@inquirer/prompts\";\nimport { allAdapters } from \"../adapters/index.js\";\nimport { listServerDefinitions } from \"../utils/server-store.js\";\nimport { resolveConfig } from \"../utils/resolve-config.js\";\nimport { isUserCancellation } from \"../utils/prompt.js\";\n\nexport async function syncCommand(): Promise<void> {\n try {\n await syncCommandInner();\n } catch (error) {\n if (isUserCancellation(error)) return;\n throw error;\n }\n}\n\nasync function syncCommandInner(): Promise<void> {\n const projectDir = process.cwd();\n\n const definitions = await listServerDefinitions();\n if (definitions.length === 0) {\n console.log(\"Central repository is empty. Nothing to sync.\");\n return;\n }\n\n const changes: Array<{\n agentName: string;\n serverName: string;\n action: \"update\" | \"skip\";\n reason?: string;\n }> = [];\n\n for (const adapter of allAdapters) {\n let servers: Record<string, unknown>;\n try {\n servers = await adapter.read(projectDir);\n } catch {\n continue;\n }\n\n for (const definition of definitions) {\n if (!(definition.name in servers)) {\n continue;\n }\n\n const currentRaw = servers[definition.name] as Record<string, unknown>;\n const desired = resolveConfig(definition, adapter);\n const desiredRaw = adapter.toAgentFormat(desired);\n\n if (JSON.stringify(currentRaw) !== JSON.stringify(desiredRaw)) {\n changes.push({\n agentName: adapter.name,\n serverName: definition.name,\n action: \"update\",\n });\n }\n }\n }\n\n if (changes.length === 0) {\n console.log(\"All agent configurations are up to date.\");\n return;\n }\n\n console.log(\"\\nSync preview:\");\n for (const change of changes) {\n console.log(` ~ ${change.serverName} -> ${change.agentName}`);\n }\n\n const proceed = await confirm({ message: \"Apply changes?\" });\n if (!proceed) {\n console.log(\"Cancelled.\");\n return;\n }\n\n for (const adapter of allAdapters) {\n for (const definition of definitions) {\n const relevant = changes.find(\n (c) =>\n c.agentName === adapter.name &&\n c.serverName === definition.name,\n );\n if (!relevant) continue;\n\n try {\n await adapter.remove(projectDir, definition.name);\n const config = resolveConfig(definition, adapter);\n await adapter.write(projectDir, definition.name, config);\n console.log(` ~ ${definition.name} -> ${adapter.name} (updated)`);\n } catch (error) {\n console.warn(\n ` ! ${definition.name} -> ${adapter.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n console.log(\"\\nSync complete.\");\n}\n","import { allAdapters } from \"../adapters/index.js\";\nimport type { AgentAdapter } from \"../types.js\";\n\ninterface ServerEntry {\n transport: string;\n}\n\nexport async function listCommand(): Promise<void> {\n const projectDir = process.cwd();\n\n const matrix: Record<string, Record<string, ServerEntry>> = {};\n const activeAdapters: AgentAdapter[] = [];\n\n for (const adapter of allAdapters) {\n let servers: Record<string, unknown>;\n try {\n servers = await adapter.read(projectDir);\n } catch {\n continue;\n }\n\n if (Object.keys(servers).length === 0) continue;\n\n activeAdapters.push(adapter);\n for (const [name, raw] of Object.entries(servers)) {\n if (!matrix[name]) {\n matrix[name] = {};\n }\n const config = adapter.fromAgentFormat(\n name,\n raw as Record<string, unknown>,\n );\n matrix[name][adapter.id] = {\n transport: config?.transport ?? \"?\",\n };\n }\n }\n\n if (Object.keys(matrix).length === 0) {\n console.log(\n \"No MCP servers found in any agent configuration. Use \\\"mcpsmgr init\\\" to get started.\",\n );\n return;\n }\n\n const serverNames = Object.keys(matrix).sort();\n const agentIds = activeAdapters.map((a) => a.id);\n const agentNames = activeAdapters.map((a) => a.name);\n\n const colWidths = [\n Math.max(6, ...serverNames.map((n) => n.length)),\n ...agentNames.map((n) => Math.max(n.length, 5)),\n ];\n\n const header = [\n \"Server\".padEnd(colWidths.at(0) ?? 6),\n ...agentNames.map((n, i) => n.padEnd(colWidths.at(i + 1) ?? 5)),\n ].join(\" \");\n\n const separator = colWidths.map((w) => \"-\".repeat(w)).join(\" \");\n\n console.log(`\\n${header}`);\n console.log(separator);\n\n for (const name of serverNames) {\n const cells = [\n name.padEnd(colWidths.at(0) ?? 6),\n ...agentIds.map((id, i) => {\n const entry = matrix[name][id];\n const val = entry ? entry.transport : \"-\";\n return val.padEnd(colWidths.at(i + 1) ?? 5);\n }),\n ];\n console.log(cells.join(\" \"));\n }\n console.log();\n}\n"],"mappings":"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","names":["mkdir","chmod","existsSync","existsSync","mkdir","chmod","confirm","input","readFile","writeFile","mkdir","chmod","existsSync","existsSync","readFile","mkdir","writeFile","chmod","input","input","confirm","server","confirm","existsSync","join","readFile","writeFile","mkdir","existsSync","join","join","readFile","writeFile","mkdir","existsSync","dirname","toAgentFormat","fromAgentFormat","existsSync","readFile","dirname","mkdir","writeFile","join","join","toAgentFormat","fromAgentFormat","join","join","toAgentFormat","fromAgentFormat","command","args","join","homedir","join","join","homedir","toAgentFormat","fromAgentFormat","existsSync","server","confirm","checkbox","checkbox","checkbox","checkbox","confirm","confirm"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# mcpsmgr
|
|
2
|
+
|
|
3
|
+
统一的 MCP (Model Context Protocol) 服务器管理工具, 支持多种 AI 编程助手.
|
|
4
|
+
|
|
5
|
+
**[English](../README.md)**
|
|
6
|
+
|
|
7
|
+
## 问题
|
|
8
|
+
|
|
9
|
+
每个 AI 编程助手 (Claude Code, Codex CLI, Gemini CLI, OpenCode, Antigravity) 都使用各自的配置格式来管理 MCP 服务器. 在多个助手之间管理相同的服务器意味着需要手动编辑多个配置文件, 既繁琐又容易出错.
|
|
10
|
+
|
|
11
|
+
## 解决方案
|
|
12
|
+
|
|
13
|
+
`mcpsmgr` 提供一个中央仓库来存储 MCP 服务器定义, 只需一条命令即可同步到所有编程助手. 定义一次, 到处部署.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
中央仓库 助手配置
|
|
17
|
+
┌──────────────────┐ ┌─► Claude Code (.claude.json)
|
|
18
|
+
│ server-a (stdio)│───┼─► Codex CLI (.codex/config.toml)
|
|
19
|
+
│ server-b (http) │ ├─► Gemini CLI (.gemini/settings.json)
|
|
20
|
+
│ server-c (stdio)│ ├─► OpenCode (.opencode.json)
|
|
21
|
+
└──────────────────┘ └─► Antigravity (.antigravity/config.json)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 特性
|
|
25
|
+
|
|
26
|
+
- **中央服务器仓库** - 在 `~/.mcps-manager/servers/` 中统一定义 MCP 服务器
|
|
27
|
+
- **多助手支持** - Claude Code, Codex CLI, Gemini CLI, OpenCode, Antigravity
|
|
28
|
+
- **AI 辅助配置** - 提供 URL 或 GitHub 仓库地址, GLM-5 自动分析文档并生成配置
|
|
29
|
+
- **按助手覆盖** - 可针对特定助手自定义服务器配置
|
|
30
|
+
- **项目级初始化** - 将选定的服务器部署到项目中检测到的助手
|
|
31
|
+
- **同步** - 将中央仓库的更新推送到所有助手配置
|
|
32
|
+
|
|
33
|
+
## 安装
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# 从源码安装
|
|
37
|
+
pnpm install
|
|
38
|
+
pnpm build
|
|
39
|
+
npm link
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 快速开始
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# 1. 初始化配置 (设置 GLM API 密钥)
|
|
46
|
+
mcpsmgr setup
|
|
47
|
+
|
|
48
|
+
# 2. 添加服务器到中央仓库
|
|
49
|
+
mcpsmgr server add https://github.com/anthropics/some-mcp-server
|
|
50
|
+
|
|
51
|
+
# 或手动添加
|
|
52
|
+
mcpsmgr server add
|
|
53
|
+
|
|
54
|
+
# 3. 初始化项目 (将服务器部署到助手)
|
|
55
|
+
cd your-project
|
|
56
|
+
mcpsmgr init
|
|
57
|
+
|
|
58
|
+
# 4. 向当前项目添加特定服务器
|
|
59
|
+
mcpsmgr add my-server
|
|
60
|
+
|
|
61
|
+
# 5. 将中央仓库的变更同步到项目
|
|
62
|
+
mcpsmgr sync
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 命令
|
|
66
|
+
|
|
67
|
+
| 命令 | 说明 |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `mcpsmgr setup` | 初始化全局配置 |
|
|
70
|
+
| `mcpsmgr server add [source]` | 添加服务器到中央仓库 (URL, GitHub owner/repo, 或手动) |
|
|
71
|
+
| `mcpsmgr server remove <name>` | 从中央仓库移除服务器 |
|
|
72
|
+
| `mcpsmgr server list` | 列出中央仓库中的所有服务器 |
|
|
73
|
+
| `mcpsmgr init` | 将服务器部署到当前项目的助手 |
|
|
74
|
+
| `mcpsmgr add <server>` | 将中央仓库的服务器添加到当前项目 |
|
|
75
|
+
| `mcpsmgr remove <server>` | 从当前项目移除服务器 |
|
|
76
|
+
| `mcpsmgr sync` | 将中央仓库的变更同步到当前项目 |
|
|
77
|
+
| `mcpsmgr list` | 列出当前项目中所有助手的 MCP 服务器 |
|
|
78
|
+
|
|
79
|
+
## 支持的助手
|
|
80
|
+
|
|
81
|
+
| 助手 | 配置位置 | 格式 |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| Claude Code | `.claude.json` (项目级) | JSON |
|
|
84
|
+
| Codex CLI | `.codex/config.toml` (项目级) | TOML |
|
|
85
|
+
| Gemini CLI | `.gemini/settings.json` (全局) | JSON |
|
|
86
|
+
| OpenCode | `.opencode.json` (项目级) | JSON |
|
|
87
|
+
| Antigravity | `.antigravity/config.json` (项目级) | JSON |
|
|
88
|
+
|
|
89
|
+
## 工作原理
|
|
90
|
+
|
|
91
|
+
1. **中央仓库** (`~/.mcps-manager/servers/`) 以 JSON 文件存储服务器定义, 每个文件包含服务器名称, 来源, 默认配置和按助手的覆盖配置.
|
|
92
|
+
|
|
93
|
+
2. **助手适配器** 理解每个助手的配置格式. 部署时, `mcpsmgr` 解析最终配置 (默认 + 覆盖) 并以助手的原生格式写入.
|
|
94
|
+
|
|
95
|
+
3. **AI 分析** (可选) 使用 GLM-5 读取 MCP 服务器文档, 自动生成服务器定义, 包括命令, 参数, 环境变量和传输类型.
|
|
96
|
+
|
|
97
|
+
## 许可证
|
|
98
|
+
|
|
99
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## Context
|
|
2
|
+
|
|
3
|
+
mcps-manager 支持 5 个 agent adapter, 其中 Antigravity 的 `isGlobal` 为 `true`, 配置文件位于 `~/.gemini/antigravity/mcp_config.json`. 由于全局配置文件几乎总是存在, `detectAgents()` 始终会检测到它, 导致在 `add`, `remove`, `init` 的交互式 checkbox 中默认选中.
|
|
4
|
+
|
|
5
|
+
当前三个命令的 checked 逻辑:
|
|
6
|
+
- `add.ts`: 所有 detected agent 都 `checked: true`
|
|
7
|
+
- `remove.ts`: 所有含该 server 的 agent 都 `checked: true`
|
|
8
|
+
- `init.ts`: detected agent `checked: true`, 其余 `checked: false`
|
|
9
|
+
|
|
10
|
+
## Goals / Non-Goals
|
|
11
|
+
|
|
12
|
+
**Goals:**
|
|
13
|
+
- 全局 agent 在交互式选择中默认不选中, 需要用户主动勾选
|
|
14
|
+
- 保持非全局 agent 的默认选中行为不变
|
|
15
|
+
- 确认 remove 只删除单个 MCP 配置, 不会批量删除 agent 下所有 MCP
|
|
16
|
+
|
|
17
|
+
**Non-Goals:**
|
|
18
|
+
- 不改变 `detectAgents()` 的检测逻辑
|
|
19
|
+
- 不改变 `isGlobal` 属性的含义
|
|
20
|
+
- 不改变 sync 命令的行为 (sync 不涉及 checkbox 选择)
|
|
21
|
+
|
|
22
|
+
## Decisions
|
|
23
|
+
|
|
24
|
+
### Decision 1: 使用 `adapter.isGlobal` 控制 checked 默认值
|
|
25
|
+
|
|
26
|
+
在所有 checkbox 的 choices 构建中, 当 `adapter.isGlobal === true` 时, `checked` 设为 `false`.
|
|
27
|
+
|
|
28
|
+
这是最简洁的方案, 直接复用已有的 `isGlobal` 属性, 无需新增字段或配置.
|
|
29
|
+
|
|
30
|
+
备选方案:
|
|
31
|
+
- 新增 `defaultChecked` 属性: 过度设计, 当前只有全局 agent 需要默认不选中
|
|
32
|
+
- 在 `detectAgents()` 中过滤全局 agent: 会影响其他依赖检测结果的逻辑
|
|
33
|
+
|
|
34
|
+
### Decision 2: 保持 remove 的单 MCP 删除语义不变
|
|
35
|
+
|
|
36
|
+
当前 `remove` 命令接收一个 `serverName` 参数, 只删除该 server 在选中 agent 中的配置. 这已经满足"不整体删除某个 agent 的所有 MCP"的要求, 无需修改逻辑, 只需调整默认选中行为.
|
|
37
|
+
|
|
38
|
+
## Risks / Trade-offs
|
|
39
|
+
|
|
40
|
+
- [全局 agent 容易被忽略] → checkbox 中 `[global]` 标签已提供视觉提示, 用户不会遗漏
|
|
41
|
+
- [用户习惯变更] → 改进方向明确, 避免误操作全局配置, 用户应该欢迎此变更
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
## Why
|
|
2
|
+
|
|
3
|
+
Antigravity 因为是全局 agent (配置文件始终存在于 `~/.gemini/antigravity/`), 在自动检测时 100% 会被检测到并默认选中. 这导致用户在 `add`, `remove`, `init` 等交互中, 每次都会不经意地操作 Antigravity 的全局配置. 需要改为默认不选中全局 agent, 让用户主动勾选.
|
|
4
|
+
|
|
5
|
+
此外, 取消选中某个 agent 时不应删除任何 MCP. 只有在选中某个 agent 的前提下, 再取消某个具体 MCP, 才会删除该 MCP 的配置. 不存在"整体删除某个 agent 的所有 MCP"的场景.
|
|
6
|
+
|
|
7
|
+
## What Changes
|
|
8
|
+
|
|
9
|
+
- 所有交互式 checkbox 中, `isGlobal` 为 `true` 的 agent 默认不选中 (checked: false)
|
|
10
|
+
- `remove` 命令中, 全局 agent 也默认不选中, 需要用户主动勾选才执行删除
|
|
11
|
+
- 确认 `remove` 的逻辑是逐个 MCP 删除, 不会批量删除某个 agent 下所有 MCP (当前实现已满足, 仅需调整默认选中行为)
|
|
12
|
+
|
|
13
|
+
## Capabilities
|
|
14
|
+
|
|
15
|
+
### New Capabilities
|
|
16
|
+
|
|
17
|
+
(无)
|
|
18
|
+
|
|
19
|
+
### Modified Capabilities
|
|
20
|
+
|
|
21
|
+
- `project-operations`: init/add/remove 命令中全局 agent 的默认选中行为变更, 全局 agent 默认不选中
|
|
22
|
+
|
|
23
|
+
## Impact
|
|
24
|
+
|
|
25
|
+
- `src/commands/add.ts`: checkbox 的 checked 逻辑
|
|
26
|
+
- `src/commands/remove.ts`: checkbox 的 checked 逻辑
|
|
27
|
+
- `src/commands/init.ts`: checkbox 的 checked 逻辑
|
|
28
|
+
- `openspec/specs/project-operations/spec.md`: 更新 spec 中关于全局 agent 默认选中行为的描述
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
## MODIFIED Requirements
|
|
2
|
+
|
|
3
|
+
### Requirement: 项目初始化
|
|
4
|
+
|
|
5
|
+
系统 SHALL 支持 `mcpsmgr init` 命令, 在当前项目中交互式选择 agent 和 MCP 服务.
|
|
6
|
+
|
|
7
|
+
#### Scenario: 交互式初始化
|
|
8
|
+
|
|
9
|
+
- **WHEN** 用户在项目目录执行 `mcpsmgr init`
|
|
10
|
+
- **THEN** 系统自动检测已存在的 agent 配置文件并预选, 展示所有支持的 agent 供用户勾选, 其中 `isGlobal` 为 `true` 的 agent (如 Antigravity) SHALL 默认不选中, 非全局 agent 按检测结果预选, 从中央仓库列出所有已保存的 MCP 服务供用户勾选, 展示即将执行的操作预览, 确认后将选中的服务写入选中的 agent 配置文件
|
|
11
|
+
|
|
12
|
+
#### Scenario: 中央仓库为空
|
|
13
|
+
|
|
14
|
+
- **WHEN** 用户执行 `mcpsmgr init` 但 `~/.mcps-manager/servers/` 下没有任何服务
|
|
15
|
+
- **THEN** 系统提示中央仓库为空, 建议先使用 `mcpsmgr server add` 添加服务
|
|
16
|
+
|
|
17
|
+
### Requirement: 项目添加服务
|
|
18
|
+
|
|
19
|
+
系统 SHALL 支持 `mcpsmgr add <server-name>` 命令, 将中央仓库中的服务添加到当前项目的 agent 配置中.
|
|
20
|
+
|
|
21
|
+
#### Scenario: 添加到已检测的 agent
|
|
22
|
+
|
|
23
|
+
- **WHEN** 用户执行 `mcpsmgr add context7`
|
|
24
|
+
- **THEN** 系统自动检测项目中已存在的 agent 配置文件, 展示列表供用户勾选, 其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中, 非全局 agent 默认选中, 将服务写入勾选的 agent 配置文件
|
|
25
|
+
|
|
26
|
+
#### Scenario: 服务不存在于中央仓库
|
|
27
|
+
|
|
28
|
+
- **WHEN** 用户执行 `mcpsmgr add nonexistent`
|
|
29
|
+
- **THEN** 系统报错, 提示服务不存在于中央仓库
|
|
30
|
+
|
|
31
|
+
#### Scenario: 部分 agent 同名冲突
|
|
32
|
+
|
|
33
|
+
- **WHEN** 添加时某些 agent 配置文件中已存在同名服务
|
|
34
|
+
- **THEN** 系统对冲突的 agent 报告跳过, 对无冲突的 agent 正常写入
|
|
35
|
+
|
|
36
|
+
### Requirement: 项目移除服务
|
|
37
|
+
|
|
38
|
+
系统 SHALL 支持 `mcpsmgr remove <server-name>` 命令, 从当前项目的 agent 配置中移除单个 MCP 服务配置.
|
|
39
|
+
|
|
40
|
+
#### Scenario: 从多个 agent 移除
|
|
41
|
+
|
|
42
|
+
- **WHEN** 用户执行 `mcpsmgr remove brave-search`
|
|
43
|
+
- **THEN** 系统列出包含该服务的所有 agent 配置, 供用户勾选要移除的, 其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中, 非全局 agent 默认选中, 从勾选的 agent 配置文件中删除该服务条目, 保留文件中的其他内容
|
|
44
|
+
|
|
45
|
+
#### Scenario: 无 agent 包含该服务
|
|
46
|
+
|
|
47
|
+
- **WHEN** 用户执行 `mcpsmgr remove nonexistent` 但没有任何 agent 配置包含该服务
|
|
48
|
+
- **THEN** 系统提示未在任何 agent 配置中找到该服务
|
|
49
|
+
|
|
50
|
+
#### Scenario: 取消选中 agent 不删除 MCP
|
|
51
|
+
|
|
52
|
+
- **WHEN** 用户在 remove 交互中取消选中某个 agent
|
|
53
|
+
- **THEN** 系统 SHALL NOT 删除该 agent 中的任何 MCP 配置, 仅跳过该 agent
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## 1. 修改 checkbox 默认选中逻辑
|
|
2
|
+
|
|
3
|
+
- [x] 1.1 修改 `src/commands/add.ts` 中 checkbox 的 checked 逻辑, 当 `adapter.isGlobal` 为 `true` 时设为 `false`
|
|
4
|
+
- [x] 1.2 修改 `src/commands/remove.ts` 中 checkbox 的 checked 逻辑, 当 `adapter.isGlobal` 为 `true` 时设为 `false`
|
|
5
|
+
- [x] 1.3 修改 `src/commands/init.ts` 中 agent 选择 checkbox 的 checked 逻辑, 当 `adapter.isGlobal` 为 `true` 时设为 `false` (覆盖检测结果)
|
|
6
|
+
|
|
7
|
+
## 2. 更新 Spec
|
|
8
|
+
|
|
9
|
+
- [x] 2.1 更新 `openspec/specs/project-operations/spec.md`, 补充全局 agent 默认不选中的行为描述
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
## Context
|
|
2
|
+
|
|
3
|
+
当前 `init` 命令在服务器选择阶段硬编码 `checked: true`, 导致所有中央仓库中的服务默认全选. 实际上 `AgentAdapter` 接口已提供 `read(projectDir)` 方法, 可以读取目标目录各 agent 配置文件中已存在的 MCP 服务. 只需在展示 checkbox 前收集已存在的服务名, 据此决定默认选中状态.
|
|
4
|
+
|
|
5
|
+
## Goals / Non-Goals
|
|
6
|
+
|
|
7
|
+
**Goals:**
|
|
8
|
+
|
|
9
|
+
- init 命令的服务器选择默认状态反映目标目录的真实配置
|
|
10
|
+
- 已存在于目标目录中的服务标记 `(detected)` 并默认选中
|
|
11
|
+
- 不存在于目标目录中的服务默认不选中
|
|
12
|
+
|
|
13
|
+
**Non-Goals:**
|
|
14
|
+
|
|
15
|
+
- 不改变 agent 选择逻辑 (已正确实现检测)
|
|
16
|
+
- 不改变 write 阶段的冲突检测机制
|
|
17
|
+
- 不修改 adapter 接口
|
|
18
|
+
|
|
19
|
+
## Decisions
|
|
20
|
+
|
|
21
|
+
### 决策 1: 使用已选中 agent 的 `read()` 方法收集已有服务名
|
|
22
|
+
|
|
23
|
+
在 agent 选择完成后, 对每个选中的 agent 调用 `read(projectDir)`, 收集所有已存在的服务名到一个 `Set<string>`. 服务器 checkbox 中, 仅当服务名存在于该 Set 中时默认选中.
|
|
24
|
+
|
|
25
|
+
**备选方案**: 在 agent 选择前就读取所有 detected agent 的配置. 但这样可能读取用户最终未选中的 agent, 且增加不必要的 IO.
|
|
26
|
+
|
|
27
|
+
**选择理由**: 基于用户实际选中的 agent 来决定, 更精确且符合用户意图.
|
|
28
|
+
|
|
29
|
+
### 决策 2: 任一 agent 包含即标记为 detected
|
|
30
|
+
|
|
31
|
+
只要有一个已选中的 agent 中包含该服务, 就认为服务是 "detected" 的. 这样更友好 - 用户不会因为部分 agent 未配置而看到服务默认不选中.
|
|
32
|
+
|
|
33
|
+
### 决策 3: read() 失败时静默降级
|
|
34
|
+
|
|
35
|
+
如果某个 agent 的 `read()` 调用失败 (如文件损坏), 跳过该 agent 的检测, 不阻断整个流程.
|
|
36
|
+
|
|
37
|
+
## Risks / Trade-offs
|
|
38
|
+
|
|
39
|
+
- [Agent 选择后才能展示服务器列表] → 这是当前已有的流程, 不改变交互顺序
|
|
40
|
+
- [read() 可能返回非 mcpsmgr 管理的手动配置的服务] → 无影响, 只是用于决定默认选中, 用户仍可手动调整
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## Why
|
|
2
|
+
|
|
3
|
+
`mcpsmgr init` 命令在展示服务器选择列表时, 所有服务器默认全部选中 (`checked: true`). 但正确行为应该是: 读取目标目录中已选中 agent 的实际 MCP 配置, 仅对已存在的服务标记为 `(detected)` 并默认选中, 不存在的服务默认不选中.
|
|
4
|
+
|
|
5
|
+
## What Changes
|
|
6
|
+
|
|
7
|
+
- 修改 `init` 命令的服务器选择逻辑, 在展示 checkbox 前先读取已选中 agent 的现有配置
|
|
8
|
+
- 对于目标目录中已存在的 MCP 服务, 显示 `(detected)` 标签并默认选中
|
|
9
|
+
- 对于目标目录中不存在的 MCP 服务, 默认不选中
|
|
10
|
+
|
|
11
|
+
## Capabilities
|
|
12
|
+
|
|
13
|
+
### New Capabilities
|
|
14
|
+
|
|
15
|
+
(无新增能力)
|
|
16
|
+
|
|
17
|
+
### Modified Capabilities
|
|
18
|
+
|
|
19
|
+
- `project-operations`: 修改 `init` 命令的服务器选择默认状态逻辑, 从 "全部选中" 改为 "基于目标目录实际配置检测"
|
|
20
|
+
|
|
21
|
+
## Impact
|
|
22
|
+
|
|
23
|
+
- 受影响文件: `src/commands/init.ts`
|
|
24
|
+
- 可能需要利用 `AgentAdapter.read()` 方法读取各 agent 的现有配置
|
|
25
|
+
- 不涉及 API 变更, 不涉及新依赖
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## MODIFIED Requirements
|
|
2
|
+
|
|
3
|
+
### Requirement: 项目初始化
|
|
4
|
+
|
|
5
|
+
系统 SHALL 支持 `mcpsmgr init` 命令, 在当前项目中交互式选择 agent 和 MCP 服务.
|
|
6
|
+
|
|
7
|
+
#### Scenario: 交互式初始化
|
|
8
|
+
|
|
9
|
+
- **WHEN** 用户在项目目录执行 `mcpsmgr init`
|
|
10
|
+
- **THEN** 系统自动检测已存在的 agent 配置文件并预选 (其中 `isGlobal` 为 `true` 的 agent SHALL 默认不选中), 展示所有支持的 agent 供用户勾选, 从中央仓库列出所有已保存的 MCP 服务供用户勾选, 展示即将执行的操作预览, 确认后将选中的服务写入选中的 agent 配置文件
|
|
11
|
+
|
|
12
|
+
#### Scenario: 服务器选择默认状态基于目标目录检测
|
|
13
|
+
|
|
14
|
+
- **WHEN** 用户完成 agent 选择后进入服务器选择步骤
|
|
15
|
+
- **THEN** 系统 SHALL 读取所有已选中 agent 的现有配置, 收集已存在的 MCP 服务名称. 对于已存在于任一已选中 agent 配置中的服务, SHALL 标记为 `(detected)` 并默认选中. 对于不存在于任何已选中 agent 配置中的服务, SHALL 默认不选中.
|
|
16
|
+
|
|
17
|
+
#### Scenario: 配置读取失败降级
|
|
18
|
+
|
|
19
|
+
- **WHEN** 读取某个已选中 agent 的现有配置时发生错误 (如文件损坏)
|
|
20
|
+
- **THEN** 系统 SHALL 跳过该 agent 的服务检测, 继续处理其他 agent, 不阻断初始化流程
|
|
21
|
+
|
|
22
|
+
#### Scenario: 中央仓库为空
|
|
23
|
+
|
|
24
|
+
- **WHEN** 用户执行 `mcpsmgr init` 但 `~/.mcps-manager/servers/` 下没有任何服务
|
|
25
|
+
- **THEN** 系统提示中央仓库为空, 建议先使用 `mcpsmgr server add` 添加服务
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## 1. 收集已选中 agent 的现有服务名
|
|
2
|
+
|
|
3
|
+
- [x] 1.1 在 `src/commands/init.ts` 中, agent 选择完成后, 遍历已选中的 agent 调用 `read(projectDir)` 收集所有已存在的服务名到 `Set<string>`, read() 失败时静默跳过
|
|
4
|
+
- [x] 1.2 修改服务器 checkbox 的 `checked` 属性, 从硬编码 `true` 改为根据服务名是否在 detected set 中决定
|
|
5
|
+
- [x] 1.3 为已检测到的服务在 checkbox 显示名称中添加 `(detected)` 标签
|
|
6
|
+
|
|
7
|
+
## 2. 验证
|
|
8
|
+
|
|
9
|
+
- [x] 2.1 在有已配置 MCP 服务的项目目录 (如 `~/workspace/coworkspace`) 手动测试, 验证已存在的服务默认选中且标记 `(detected)`, 不存在的服务默认不选中
|
|
10
|
+
- [x] 2.2 在无任何 agent 配置的空目录测试, 验证所有服务默认不选中
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## Context
|
|
2
|
+
|
|
3
|
+
所有交互式命令 (init, setup, add, remove, server-add, sync) 使用 `@inquirer/prompts` 进行用户交互. 当用户按 Ctrl-C 时, inquirer 抛出 `ExitPromptError` 异常. 当前没有任何命令捕获此异常, 导致程序以错误堆栈退出.
|
|
4
|
+
|
|
5
|
+
## Goals / Non-Goals
|
|
6
|
+
|
|
7
|
+
**Goals:**
|
|
8
|
+
- 用户在任何交互式 prompt 中按 Ctrl-C 时, 程序静默正常退出
|
|
9
|
+
- 统一处理, 避免每个命令重复编写 try-catch
|
|
10
|
+
|
|
11
|
+
**Non-Goals:**
|
|
12
|
+
- 不添加 'q' 键退出 (inquirer 不原生支持, 且 q 可能是合法输入)
|
|
13
|
+
- 不改变业务逻辑或 prompt 行为
|
|
14
|
+
- 不处理非交互式命令的中断
|
|
15
|
+
|
|
16
|
+
## Decisions
|
|
17
|
+
|
|
18
|
+
### Decision 1: 统一工具函数捕获 ExitPromptError
|
|
19
|
+
|
|
20
|
+
提取一个 `isUserCancellation(error)` 工具函数, 判断错误是否为用户主动取消. 在各命令的顶层 action handler 中统一 try-catch, 捕获后静默 return.
|
|
21
|
+
|
|
22
|
+
**备选方案**: 在每个 prompt 调用处逐一 try-catch → 太冗余, 容易遗漏.
|
|
23
|
+
|
|
24
|
+
**备选方案**: 全局 process-level uncaughtException handler → 过于激进, 可能掩盖真实错误.
|
|
25
|
+
|
|
26
|
+
### Decision 2: 退出码为 0
|
|
27
|
+
|
|
28
|
+
用户主动取消是正常行为, 不是错误. 退出码应为 0.
|
|
29
|
+
|
|
30
|
+
## Risks / Trade-offs
|
|
31
|
+
|
|
32
|
+
- [Risk] 新增的 prompt 调用忘记包裹 → 通过在命令 action 顶层统一 catch 来规避, 只要命令内部抛出的 ExitPromptError 会自然冒泡到顶层
|