feat(cli): auto-discover MCP servers in .continue/mcpServers#12922
feat(cli): auto-discover MCP servers in .continue/mcpServers#12922Rakesh1002 wants to merge 1 commit into
Conversation
The CLI only loaded MCP servers from the active config's mcpServers block, `uses` references, and --mcp/--agent flags. Unlike the IDE extensions, it ignored standalone server files dropped into .continue/mcpServers, which the docs describe as the quick-start path. Add loadJsonMcpServers, which scans the workspace .continue/mcpServers and the global ~/.continue/mcpServers for JSON files (single-server, Claude-desktop, and Claude-code formats), converts them to the assistant mcpServers shape, and de-duplicates by name. ConfigService merges the discovered servers into the unrolled assistant, bringing the CLI to parity with the IDE. Closes continuedev#12254
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
4 issues found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="extensions/cli/src/services/loadJsonMcpServers.test.ts">
<violation number="1" location="extensions/cli/src/services/loadJsonMcpServers.test.ts:54">
P3: Weak assertion in Claude-desktop test: only checks server name, does not verify command/args properties are correctly parsed through convertJsonMcpConfigToYamlMcpConfig</violation>
</file>
<file name="extensions/cli/src/services/ConfigService.ts">
<violation number="1" location="extensions/cli/src/services/ConfigService.ts:162">
P2: The new MCP JSON discovery hook is not guarded inside ConfigService, so an unexpected exception from `loadJsonMcpServers` can abort config loading, startup, switchConfig, or reload instead of being treated as an optional discovery failure with a warning.</violation>
<violation number="2" location="extensions/cli/src/services/ConfigService.ts:163">
P2: Auto-discovered MCP servers should be filtered against servers already present in `additional.mcpServers` before pushing, and the precedence relative to the loaded assistant config should be explicit. Currently the JSON discovery path appends blindly, relying on downstream merge order and risking silent override of config-defined servers.</violation>
</file>
<file name="extensions/cli/src/services/loadJsonMcpServers.ts">
<violation number="1" location="extensions/cli/src/services/loadJsonMcpServers.ts:76">
P2: Workspace MCP server discovery defaults to `process.cwd()`, which may miss `.continue/mcpServers/` at the project root when `cn` is launched from a subdirectory. The IDE equivalent resolves actual workspace directories instead of relying on the shell cwd.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| } | ||
|
|
||
| private processJsonMcpServers(additional: AssistantUnrolled): void { | ||
| for (const server of loadJsonMcpServers()) { |
There was a problem hiding this comment.
P2: Auto-discovered MCP servers should be filtered against servers already present in additional.mcpServers before pushing, and the precedence relative to the loaded assistant config should be explicit. Currently the JSON discovery path appends blindly, relying on downstream merge order and risking silent override of config-defined servers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/cli/src/services/ConfigService.ts, line 163:
<comment>Auto-discovered MCP servers should be filtered against servers already present in `additional.mcpServers` before pushing, and the precedence relative to the loaded assistant config should be explicit. Currently the JSON discovery path appends blindly, relying on downstream merge order and risking silent override of config-defined servers.</comment>
<file context>
@@ -157,6 +159,12 @@ export class ConfigService
}
+ private processJsonMcpServers(additional: AssistantUnrolled): void {
+ for (const server of loadJsonMcpServers()) {
+ additional.mcpServers!.push(server);
+ }
</file context>
| private processJsonMcpServers(additional: AssistantUnrolled): void { | ||
| for (const server of loadJsonMcpServers()) { | ||
| additional.mcpServers!.push(server); | ||
| } | ||
| } |
There was a problem hiding this comment.
P2: The new MCP JSON discovery hook is not guarded inside ConfigService, so an unexpected exception from loadJsonMcpServers can abort config loading, startup, switchConfig, or reload instead of being treated as an optional discovery failure with a warning.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/cli/src/services/ConfigService.ts, line 162:
<comment>The new MCP JSON discovery hook is not guarded inside ConfigService, so an unexpected exception from `loadJsonMcpServers` can abort config loading, startup, switchConfig, or reload instead of being treated as an optional discovery failure with a warning.</comment>
<file context>
@@ -157,6 +159,12 @@ export class ConfigService
}
}
+ private processJsonMcpServers(additional: AssistantUnrolled): void {
+ for (const server of loadJsonMcpServers()) {
+ additional.mcpServers!.push(server);
</file context>
| private processJsonMcpServers(additional: AssistantUnrolled): void { | |
| for (const server of loadJsonMcpServers()) { | |
| additional.mcpServers!.push(server); | |
| } | |
| } | |
| private processJsonMcpServers(additional: AssistantUnrolled): void { | |
| try { | |
| for (const server of loadJsonMcpServers()) { | |
| additional.mcpServers!.push(server); | |
| } | |
| } catch (e) { | |
| logger.warn(`Failed to load JSON MCP servers: ${getErrorString(e)}`); | |
| } | |
| } |
| * Returns configs in the same shape as the rest of the assistant's mcpServers. | ||
| */ | ||
| export function loadJsonMcpServers( | ||
| cwd: string = process.cwd(), |
There was a problem hiding this comment.
P2: Workspace MCP server discovery defaults to process.cwd(), which may miss .continue/mcpServers/ at the project root when cn is launched from a subdirectory. The IDE equivalent resolves actual workspace directories instead of relying on the shell cwd.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/cli/src/services/loadJsonMcpServers.ts, line 76:
<comment>Workspace MCP server discovery defaults to `process.cwd()`, which may miss `.continue/mcpServers/` at the project root when `cn` is launched from a subdirectory. The IDE equivalent resolves actual workspace directories instead of relying on the shell cwd.</comment>
<file context>
@@ -0,0 +1,134 @@
+ * Returns configs in the same shape as the rest of the assistant's mcpServers.
+ */
+export function loadJsonMcpServers(
+ cwd: string = process.cwd(),
+): MCPServerConfig[] {
+ const servers: MCPServerConfig[] = [];
</file context>
|
|
||
| const servers = loadJsonMcpServers(cwd); | ||
|
|
||
| expect(servers.map((s) => s.name)).toEqual(["weather"]); |
There was a problem hiding this comment.
P3: Weak assertion in Claude-desktop test: only checks server name, does not verify command/args properties are correctly parsed through convertJsonMcpConfigToYamlMcpConfig
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At extensions/cli/src/services/loadJsonMcpServers.test.ts, line 54:
<comment>Weak assertion in Claude-desktop test: only checks server name, does not verify command/args properties are correctly parsed through convertJsonMcpConfigToYamlMcpConfig</comment>
<file context>
@@ -0,0 +1,91 @@
+
+ const servers = loadJsonMcpServers(cwd);
+
+ expect(servers.map((s) => s.name)).toEqual(["weather"]);
+ });
+
</file context>
Description
Closes #12254.
The CLI (
cn) only discovers MCP servers from four sources: the active config'smcpServers:block,uses:references resolved by the unroller,--mcp, and--agentfiles. Unlike the IDE extensions, it ignores standalone server files placed in.continue/mcpServers/— even though the docs describe that directory as the quick-start path.Change
Adds
loadJsonMcpServers(extensions/cli/src/services/loadJsonMcpServers.ts), which mirrors the IDE'score/context/mcp/json/loadJsonMcpConfigs.ts:.continue/mcpServers/and the global~/.continue/mcpServers/(viaenv.continueHome, matching the existing skills loader)..jsonfiles in all three formats the IDE supports — single-server, Claude-desktop ({ "mcpServers": { … } }), and Claude-code (top-level + per-project) — reusing@continuedev/config-yaml's schemas andconvertJsonMcpConfigToYamlMcpConfigso the output matches the assistant'smcpServersshape.ConfigService.getAdditionalBlocksFromOptionsmerges the discovered servers into the unrolled assistant, socnnow reaches parity with the IDE.Tests
loadJsonMcpServers.test.ts— 6 vitest cases against the real@continuedev/config-yaml(empty dir, single stdio file named after the file, Claude-desktop map, http transport mapping, invalid-file skip, name de-duplication).npm run lint+tsc --noEmitpass; existingConfigService/MCPServicesuites unaffected.Notes
.jsonto match the IDE's loader (which filters to.json); YAML discovery could be a follow-up.JSON.parse(no new dependency); switching to JSONC for comment support is a possible follow-up.Summary by cubic
Add CLI auto-discovery of MCP servers from
.continue/mcpServers(workspace and global) and merge them into the assistant config, bringingcnto parity with the IDE. Supports single-server, Claude Desktop, and Claude Code JSON formats with name de-dupe and safe skips.loadJsonMcpServersto scan workspace andenv.continueHome.continue/mcpServers/..jsonfiles in supported formats using@continuedev/config-yamlschemas andconvertJsonMcpConfigToYamlMcpConfig.ConfigService.getAdditionalBlocksFromOptions.httptostreamable-http.Written for commit a129774. Summary will update on new commits.