MCP SSE support (#511)

Matches the config format used by other MCP clients.
This commit is contained in:
cornmander 2025-05-23 17:19:30 -04:00 committed by GitHub
parent 8590efd229
commit 635666dec9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 16 deletions

View File

@ -24,10 +24,14 @@ import { WebSearchTool } from '../tools/web-search.js';
export class MCPServerConfig {
constructor(
readonly command: string,
// For stdio transport
readonly command?: string,
readonly args?: string[],
readonly env?: Record<string, string>,
readonly cwd?: string,
// For sse transport
readonly url?: string,
// Common
readonly timeout?: number,
) {}
}

View File

@ -12,6 +12,7 @@ import { spawn, execSync } from 'node:child_process';
// TODO: remove this dependency once MCP support is built into genai SDK
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
type ToolParams = Record<string, unknown>;
const MCP_TOOL_DEFAULT_TIMEOUT_MSEC = 10 * 60 * 1000; // default to 10 minutes
@ -206,14 +207,28 @@ export class ToolRegistry {
name: 'mcp-client',
version: '0.0.1',
});
const transport = new StdioClientTransport({
...mcpServerConfig,
let transport;
if (mcpServerConfig.url) {
// SSE transport if URL is provided
transport = new SSEClientTransport(new URL(mcpServerConfig.url));
} else if (mcpServerConfig.command) {
// Stdio transport if command is provided
transport = new StdioClientTransport({
command: mcpServerConfig.command,
args: mcpServerConfig.args || [],
env: {
...process.env,
...(mcpServerConfig.env || {}),
} as Record<string, string>,
cwd: mcpServerConfig.cwd,
stderr: 'pipe',
});
} else {
console.error(
`MCP server '${mcpServerName}' has invalid configuration: missing both url (for SSE) and command (for stdio). Skipping.`,
);
return;
}
try {
await mcpClient.connect(transport);
} catch (error) {
@ -227,15 +242,17 @@ export class ToolRegistry {
mcpClient.onerror = (error) => {
console.error('MCP ERROR', error.toString());
};
if (!transport.stderr) {
if (transport instanceof StdioClientTransport && !transport.stderr) {
throw new Error('transport missing stderr stream');
}
transport.stderr.on('data', (data) => {
if (transport instanceof StdioClientTransport) {
transport.stderr!.on('data', (data) => {
// filter out INFO messages logged for each request received
if (!data.toString().includes('] INFO')) {
console.debug('MCP STDERR', data.toString());
}
});
}
const result = await mcpClient.listTools();
for (const tool of result.tools) {
// Recursively remove additionalProperties and $schema from the inputSchema