Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions common/src/mcp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ function hashConfig(config: MCPConfig): string {
type: 'http',
url: config.url,
params: config.params,
headers: config.headers,
})
}
if (config.type === 'sse') {
return JSON.stringify({
type: 'sse',
url: config.url,
params: config.params,
headers: config.headers,
})
}
config.type satisfies never
Expand Down Expand Up @@ -231,3 +233,25 @@ export async function callMCPTool(
} satisfies ToolResultOutput
})
}

/**
* Close an MCP client connection and clean up associated resources.
*
* Removes the client from the running clients registry and clears any cached
* tool listings. The underlying transport (stdio child process, HTTP/SSE
* connection) is also torn down via the MCP SDK's client.close() method.
*
* Safe to call on an already-closed or unknown client id (no-ops silently).
*/
export async function closeMCPClient(clientId: string): Promise<void> {
const client = runningClients[clientId]
if (client) {
try {
await client.close()
} catch {
// Ignore errors during close — the transport may already be dead.
}
delete runningClients[clientId]
}
delete listToolsCache[clientId]
}
9 changes: 8 additions & 1 deletion sdk/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
getMCPClient,
listMCPTools,
callMCPTool,
closeMCPClient,
} from '@codebuff/common/mcp/client'
import {
COMPOSIO_META_TOOL_NAMES,
Expand Down Expand Up @@ -809,8 +810,9 @@ async function handleToolCall({

// Handle MCP tool calls when mcpConfig is present
if (action.mcpConfig) {
let mcpClientId: string | undefined
try {
const mcpClientId = await getMCPClient(action.mcpConfig)
mcpClientId = await getMCPClient(action.mcpConfig)
const result = await callMCPTool(
mcpClientId,
{
Expand All @@ -822,6 +824,11 @@ async function handleToolCall({
)
return { output: result }
} catch (error) {
// Clean up the dead client so the next call reconnects with a fresh
// transport rather than hitting the same broken connection.
if (mcpClientId) {
closeMCPClient(mcpClientId).catch(() => {})
}
return {
output: [
{
Expand Down