(config: MCPConfig)
| 75 | } |
| 76 | |
| 77 | export async function getMCPClient(config: MCPConfig): Promise<string> { |
| 78 | let key = hashConfig(config) |
| 79 | if (key in runningClients) { |
| 80 | return key |
| 81 | } |
| 82 | |
| 83 | let transport: Transport |
| 84 | if (config.type === 'stdio') { |
| 85 | transport = new StdioClientTransport({ |
| 86 | command: config.command, |
| 87 | args: config.args, |
| 88 | env: substituteEnvInRecord(config.env), |
| 89 | stderr: 'ignore', |
| 90 | }) |
| 91 | } else { |
| 92 | const url = new URL(config.url) |
| 93 | for (const [key, value] of Object.entries(config.params)) { |
| 94 | url.searchParams.set(key, value) |
| 95 | } |
| 96 | const headers = substituteEnvInRecord(config.headers) |
| 97 | if (config.type === 'http') { |
| 98 | transport = new StreamableHTTPClientTransport(url, { |
| 99 | requestInit: { |
| 100 | headers, |
| 101 | }, |
| 102 | }) |
| 103 | } else if (config.type === 'sse') { |
| 104 | transport = new SSEClientTransport(url, { |
| 105 | requestInit: { |
| 106 | headers, |
| 107 | }, |
| 108 | }) |
| 109 | } else { |
| 110 | config.type satisfies never |
| 111 | throw new Error(`Internal error: invalid MCP config type ${config.type}`) |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | const client = new Client({ |
| 116 | name: 'codebuff', |
| 117 | version: '1.0.0', |
| 118 | }) |
| 119 | |
| 120 | await client.connect(transport) |
| 121 | runningClients[key] = client |
| 122 | |
| 123 | return key |
| 124 | } |
| 125 | |
| 126 | export function listMCPTools( |
| 127 | clientId: string, |
no test coverage detected