Skip to content

Commit b35feff

Browse files
committed
feat: add getAllMcpTools function with example and overloads [AI]
1 parent 0171e90 commit b35feff

File tree

4 files changed

+160
-10
lines changed

4 files changed

+160
-10
lines changed

examples/mcp/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ pnpm -F mcp start:stdio
1818
```bash
1919
pnpm -F mcp start:tool-filter
2020
```
21+
22+
`get-all-mcp-tools-example.ts` demonstrates how to use the `getAllMcpTools` function to fetch tools from multiple MCP servers:
23+
24+
```bash
25+
pnpm -F mcp start:get-all-tools
26+
```
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import {
2+
Agent,
3+
run,
4+
MCPServerStdio,
5+
getAllMcpTools,
6+
withTrace,
7+
} from '@openai/agents';
8+
import * as path from 'node:path';
9+
import { createOpenAI } from '@ai-sdk/openai';
10+
import { aisdk } from '@openai/agents-extensions';
11+
12+
const openai = createOpenAI({
13+
baseURL: 'https://api.moonshot.cn/v1',
14+
apiKey: process.env.MOONSHOT_API_KEY,
15+
});
16+
17+
const model = aisdk(openai('kimi-k2-turbo-preview'));
18+
19+
async function main() {
20+
const samplesDir = path.join(__dirname, 'sample_files');
21+
22+
// Create multiple MCP servers to demonstrate getAllMcpTools
23+
const filesystemServer = new MCPServerStdio({
24+
name: 'Filesystem Server',
25+
fullCommand: `npx -y @modelcontextprotocol/server-filesystem ${samplesDir}`,
26+
});
27+
28+
// Note: This example shows how to use multiple servers
29+
// In practice, you would have different servers with different tools
30+
const servers = [filesystemServer];
31+
32+
// Connect all servers
33+
for (const server of servers) {
34+
await server.connect();
35+
}
36+
37+
try {
38+
await withTrace('getAllMcpTools Example', async () => {
39+
console.log('=== Using getAllMcpTools to fetch all tools ===\n');
40+
41+
// Method 1: Simple array of servers
42+
const allTools = await getAllMcpTools(servers);
43+
console.log(
44+
`Found ${allTools.length} tools from ${servers.length} server(s):`,
45+
);
46+
allTools.forEach((tool) => {
47+
const description =
48+
tool.type === 'function' ? tool.description : 'No description';
49+
console.log(`- ${tool.name}: ${description}`);
50+
});
51+
52+
console.log('\n=== Using getAllMcpTools with options object ===\n');
53+
54+
// Method 2: Using options object (recommended for more control)
55+
const allToolsWithOptions = await getAllMcpTools({
56+
mcpServers: servers,
57+
convertSchemasToStrict: true, // Convert schemas to strict mode
58+
});
59+
60+
console.log(
61+
`Found ${allToolsWithOptions.length} tools with strict schemas:`,
62+
);
63+
allToolsWithOptions.forEach((tool) => {
64+
const description =
65+
tool.type === 'function' ? tool.description : 'No description';
66+
console.log(`- ${tool.name}: ${description}`);
67+
});
68+
69+
console.log('\n=== Creating agent with pre-fetched tools ===\n');
70+
71+
// Create agent using the pre-fetched tools
72+
const agent = new Agent({
73+
name: 'MCP Assistant with Pre-fetched Tools',
74+
instructions:
75+
'Use the available tools to help the user with file operations.',
76+
tools: allTools, // Use pre-fetched tools instead of mcpServers
77+
model,
78+
});
79+
80+
// Test the agent
81+
const message = 'List the available files and read one of them.';
82+
console.log(`Running: ${message}\n`);
83+
const result = await run(agent, message);
84+
console.log(result.finalOutput);
85+
86+
console.log(
87+
'\n=== Demonstrating tool filtering with getAllMcpTools ===\n',
88+
);
89+
90+
// Add tool filter to one of the servers
91+
filesystemServer.toolFilter = {
92+
allowedToolNames: ['read_file'], // Only allow read_file tool
93+
};
94+
95+
// Note: For callable filters to work, you need to pass runContext and agent
96+
// This is typically done internally when the agent runs
97+
const filteredTools = await getAllMcpTools({
98+
mcpServers: servers,
99+
convertSchemasToStrict: false,
100+
// runContext and agent would normally be provided by the agent runtime
101+
// For demo purposes, we're showing the structure
102+
});
103+
104+
console.log(`After filtering, found ${filteredTools.length} tools:`);
105+
filteredTools.forEach((tool) => {
106+
console.log(`- ${tool.name}`);
107+
});
108+
});
109+
} finally {
110+
// Clean up - close all servers
111+
for (const server of servers) {
112+
await server.close();
113+
}
114+
}
115+
}
116+
117+
main().catch((err) => {
118+
console.error('Error:', err);
119+
process.exit(1);
120+
});

examples/mcp/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
"dependencies": {
55
"@modelcontextprotocol/sdk": "^1.12.0",
66
"@openai/agents": "workspace:*",
7-
"zod": "3.25.40 - 3.25.67"
7+
"zod": "3.25.40 - 3.25.67",
8+
"@openai/agents-extensions": "workspace:*",
9+
"@ai-sdk/openai": "^1.1.3"
810
},
911
"scripts": {
1012
"build-check": "tsc --noEmit",
@@ -14,6 +16,7 @@
1416
"start:hosted-mcp-human-in-the-loop": "tsx hosted-mcp-human-in-the-loop.ts",
1517
"start:hosted-mcp-simple": "tsx hosted-mcp-simple.ts",
1618
"start:tool-filter": "tsx tool-filter-example.ts",
17-
"start:sse": "tsx sse-example.ts"
19+
"start:sse": "tsx sse-example.ts",
20+
"start:get-all-tools": "tsx get-all-mcp-tools-example.ts"
1821
}
1922
}

packages/agents-core/src/mcp.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,21 +392,42 @@ export type GetAllMcpToolsOptions<TContext> = {
392392
* Returns all MCP tools from the provided servers, using the function tool conversion.
393393
* If runContext and agent are provided, callable tool filters will be applied.
394394
*/
395-
export async function getAllMcpTools<TContext = UnknownContext>({
396-
mcpServers,
395+
export async function getAllMcpTools<TContext = UnknownContext>(
396+
mcpServers: MCPServer[],
397+
): Promise<Tool<TContext>[]>;
398+
export async function getAllMcpTools<TContext = UnknownContext>(
399+
opts: GetAllMcpToolsOptions<TContext>,
400+
): Promise<Tool<TContext>[]>;
401+
export async function getAllMcpTools<TContext = UnknownContext>(
402+
mcpServersOrOpts: MCPServer[] | GetAllMcpToolsOptions<TContext>,
403+
runContext?: RunContext<TContext>,
404+
agent?: Agent<TContext, any>,
397405
convertSchemasToStrict = false,
398-
runContext,
399-
agent,
400-
}: GetAllMcpToolsOptions<TContext>): Promise<Tool<TContext>[]> {
406+
): Promise<Tool<TContext>[]> {
407+
const opts = Array.isArray(mcpServersOrOpts)
408+
? {
409+
mcpServers: mcpServersOrOpts,
410+
runContext,
411+
agent,
412+
convertSchemasToStrict,
413+
}
414+
: mcpServersOrOpts;
415+
416+
const {
417+
mcpServers,
418+
convertSchemasToStrict: convertSchemasToStrictFromOpts = false,
419+
runContext: runContextFromOpts,
420+
agent: agentFromOpts,
421+
} = opts;
401422
const allTools: Tool<TContext>[] = [];
402423
const toolNames = new Set<string>();
403424

404425
for (const server of mcpServers) {
405426
const serverTools = await getFunctionToolsFromServer({
406427
server,
407-
convertSchemasToStrict,
408-
runContext,
409-
agent,
428+
convertSchemasToStrict: convertSchemasToStrictFromOpts,
429+
runContext: runContextFromOpts,
430+
agent: agentFromOpts,
410431
});
411432
const serverToolNames = new Set(serverTools.map((t) => t.name));
412433
const intersection = [...serverToolNames].filter((n) => toolNames.has(n));

0 commit comments

Comments
 (0)