Skip to content

Commit af73bfb

Browse files
authored
fix(mcp): rebind cached tools to connected server (#195) (#223)
1 parent 40dc0be commit af73bfb

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

.changeset/funny-dragons-tell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openai/agents-core': patch
3+
---
4+
5+
Rebinds cached tools to the current MCP server to avoid stale tool invocation (fixes #195)

packages/agents-core/src/mcp.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export async function getAllMcpFunctionTools<TContext = UnknownContext>(
219219
return allTools;
220220
}
221221

222-
const _cachedTools: Record<string, FunctionTool<any, any, unknown>[]> = {};
222+
const _cachedTools: Record<string, MCPTool[]> = {};
223223
/**
224224
* Remove cached tools for the given server so the next lookup fetches fresh data.
225225
*
@@ -236,7 +236,9 @@ async function getFunctionToolsFromServer<TContext = UnknownContext>(
236236
convertSchemasToStrict: boolean,
237237
): Promise<FunctionTool<TContext, any, unknown>[]> {
238238
if (server.cacheToolsList && _cachedTools[server.name]) {
239-
return _cachedTools[server.name];
239+
return _cachedTools[server.name].map((t) =>
240+
mcpToFunctionTool(t, server, convertSchemasToStrict),
241+
);
240242
}
241243
return withMCPListToolsSpan(
242244
async (span) => {
@@ -246,7 +248,7 @@ async function getFunctionToolsFromServer<TContext = UnknownContext>(
246248
mcpToFunctionTool(t, server, convertSchemasToStrict),
247249
);
248250
if (server.cacheToolsList) {
249-
_cachedTools[server.name] = tools;
251+
_cachedTools[server.name] = mcpTools;
250252
}
251253
return tools;
252254
},

packages/agents-core/test/mcpCache.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, it, expect } from 'vitest';
22
import { getAllMcpTools } from '../src/mcp';
3+
import type { FunctionTool } from '../src/tool';
34
import { withTrace } from '../src/tracing';
45
import { NodeMCPServerStdio } from '../src/shims/mcp-server/node';
56
import type { CallToolResultContent } from '../src/mcp';
@@ -60,4 +61,31 @@ describe('MCP tools cache invalidation', () => {
6061
expect(tools.map((t) => t.name)).toEqual(['b']);
6162
});
6263
});
64+
65+
it('binds cached tools to the current server instance', async () => {
66+
await withTrace('test', async () => {
67+
const tools = [
68+
{
69+
name: 'a',
70+
description: '',
71+
inputSchema: { type: 'object', properties: {} },
72+
},
73+
];
74+
75+
const serverA = new StubServer('server', tools);
76+
await getAllMcpTools([serverA]);
77+
78+
const serverB = new StubServer('server', tools);
79+
let called = false;
80+
(serverB as any).callTool = async () => {
81+
called = true;
82+
return [];
83+
};
84+
85+
const cachedTools = (await getAllMcpTools([serverB])) as FunctionTool[];
86+
await cachedTools[0].invoke({} as any, '{}');
87+
88+
expect(called).toBe(true);
89+
});
90+
});
6391
});

0 commit comments

Comments
 (0)