feat: implement SDK MCP server support and enhance control request handling

- Added new `SdkMcpController` to manage communication between CLI MCP clients and SDK MCP servers.
- Introduced `createSdkMcpServer` function for creating SDK-embedded MCP servers.
- Updated configuration options to support both external and SDK MCP servers.
- Enhanced timeout settings for various SDK operations, including MCP requests.
- Refactored existing control request handling to accommodate new SDK MCP server functionality.
- Updated tests to cover new SDK MCP server features and ensure proper integration.
This commit is contained in:
mingholy.lmh
2025-12-04 17:01:13 +08:00
parent a58d3f7aaf
commit 322ce80e2c
29 changed files with 2473 additions and 837 deletions

View File

@@ -5,6 +5,7 @@
*/
import type { Config, MCPServerConfig } from '../config/config.js';
import { isSdkMcpServerConfig } from '../config/config.js';
import type { ToolRegistry } from './tool-registry.js';
import type { PromptRegistry } from '../prompts/prompt-registry.js';
import {
@@ -12,6 +13,7 @@ import {
MCPDiscoveryState,
populateMcpServerCommand,
} from './mcp-client.js';
import type { SendSdkMcpMessage } from './mcp-client.js';
import { getErrorMessage } from '../utils/errors.js';
import type { EventEmitter } from 'node:events';
import type { WorkspaceContext } from '../utils/workspaceContext.js';
@@ -31,6 +33,7 @@ export class McpClientManager {
private readonly workspaceContext: WorkspaceContext;
private discoveryState: MCPDiscoveryState = MCPDiscoveryState.NOT_STARTED;
private readonly eventEmitter?: EventEmitter;
private readonly sendSdkMcpMessage?: SendSdkMcpMessage;
constructor(
mcpServers: Record<string, MCPServerConfig>,
@@ -40,6 +43,7 @@ export class McpClientManager {
debugMode: boolean,
workspaceContext: WorkspaceContext,
eventEmitter?: EventEmitter,
sendSdkMcpMessage?: SendSdkMcpMessage,
) {
this.mcpServers = mcpServers;
this.mcpServerCommand = mcpServerCommand;
@@ -48,6 +52,7 @@ export class McpClientManager {
this.debugMode = debugMode;
this.workspaceContext = workspaceContext;
this.eventEmitter = eventEmitter;
this.sendSdkMcpMessage = sendSdkMcpMessage;
}
/**
@@ -71,6 +76,11 @@ export class McpClientManager {
this.eventEmitter?.emit('mcp-client-update', this.clients);
const discoveryPromises = Object.entries(servers).map(
async ([name, config]) => {
// For SDK MCP servers, pass the sendSdkMcpMessage callback
const sdkCallback = isSdkMcpServerConfig(config)
? this.sendSdkMcpMessage
: undefined;
const client = new McpClient(
name,
config,
@@ -78,6 +88,7 @@ export class McpClientManager {
this.promptRegistry,
this.workspaceContext,
this.debugMode,
sdkCallback,
);
this.clients.set(name, client);