Skip to content

Commit 52293ee

Browse files
committed
Add allowed_tools and headers to hosted mcp server factory method
1 parent 2fae25c commit 52293ee

File tree

7 files changed

+39
-19
lines changed

7 files changed

+39
-19
lines changed

examples/mcp/filesystem-example.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async function main() {
1616
try {
1717
await withTrace('MCP Filesystem Example', async () => {
1818
const agent = new Agent({
19-
name: 'Assistant',
19+
name: 'MCP Assistant',
2020
instructions:
2121
'Use the tools to read the filesystem and answer questions based on those files. If you are unable to find any files, you can say so instead of assuming they exist.',
2222
mcpServers: [mcpServer],
@@ -25,20 +25,20 @@ async function main() {
2525
let message = 'Read the files and list them.';
2626
console.log(`Running: ${message}`);
2727
let result = await run(agent, message);
28-
console.log(result.finalOutput ?? result.output ?? result);
28+
console.log(result.finalOutput);
2929

3030
// Ask about books
3131
message = 'What is my #1 favorite book?';
3232
console.log(`\nRunning: ${message}\n`);
3333
result = await run(agent, message);
34-
console.log(result.finalOutput ?? result.output ?? result);
34+
console.log(result.finalOutput);
3535

3636
// Ask a question that reads then reasons
3737
message =
3838
'Look at my favorite songs. Suggest one new song that I might like.';
3939
console.log(`\nRunning: ${message}\n`);
4040
result = await run(agent, message);
41-
console.log(result.finalOutput ?? result.output ?? result);
41+
console.log(result.finalOutput);
4242
});
4343
} finally {
4444
await mcpServer.close();

examples/mcp/hosted-mcp-human-in-the-loop.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import * as readline from 'readline/promises';
2-
import { stdin, stdout } from 'node:process';
31
import { Agent, run, hostedMcpTool, RunToolApprovalItem } from '@openai/agents';
2+
import * as readline from 'node:readline/promises';
3+
import { stdin, stdout } from 'node:process';
44

5-
async function promptApproval(item: RunToolApprovalItem): Promise<boolean> {
5+
async function confirm(item: RunToolApprovalItem): Promise<boolean> {
66
const rl = readline.createInterface({ input: stdin, output: stdout });
77
const name = item.rawItem.name;
88
const params = JSON.parse(item.rawItem.providerData?.arguments || '{}');
@@ -14,9 +14,7 @@ async function promptApproval(item: RunToolApprovalItem): Promise<boolean> {
1414
}
1515

1616
async function main(verbose: boolean, stream: boolean): Promise<void> {
17-
// 'always' |
18-
// 'never' |
19-
// { never?: { toolNames: string[] }; always?: { toolNames: string[] } }
17+
// 'always' | 'never' | { never, always }
2018
const requireApproval = {
2119
never: { toolNames: ['search_codex_code', 'fetch_codex_documentation'] },
2220
always: { toolNames: ['fetch_generic_url_content'] },
@@ -54,17 +52,18 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
5452
console.log(`Done streaming; final result: ${result.finalOutput}`);
5553
} else {
5654
// Non-streaming
57-
let result = await run(agent, input, { maxTurns: 100 });
55+
let result = await run(agent, input);
5856
while (result.interruptions && result.interruptions.length) {
5957
for (const interruption of result.interruptions) {
60-
const approval = await promptApproval(interruption);
58+
// Human in the loop here
59+
const approval = await confirm(interruption);
6160
if (approval) {
6261
result.state.approve(interruption);
6362
} else {
6463
result.state.reject(interruption);
6564
}
6665
}
67-
result = await run(agent, result.state, { maxTurns: 100 });
66+
result = await run(agent, result.state);
6867
}
6968
console.log(result.finalOutput);
7069

examples/mcp/hosted-mcp-on-approval.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ async function promptApproval(item: RunToolApprovalItem): Promise<boolean> {
1414
}
1515

1616
async function main(verbose: boolean, stream: boolean): Promise<void> {
17-
// 'always' |
18-
// 'never' |
19-
// { never?: { toolNames: string[] }; always?: { toolNames: string[] } }
17+
// 'always' | 'never' | { never, always }
2018
const requireApproval = {
2119
never: {
2220
toolNames: ['fetch_codex_documentation', 'fetch_generic_url_content'],
@@ -34,6 +32,7 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
3432
serverUrl: 'https://gitmcp.io/openai/codex',
3533
requireApproval,
3634
onApproval: async (_context, item) => {
35+
// Human in the loop here
3736
const approval = await promptApproval(item);
3837
return { approve: approval, reason: undefined };
3938
},

examples/mcp/hosted-mcp-simple.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ async function main(verbose: boolean, stream: boolean): Promise<void> {
99
hostedMcpTool({
1010
serverLabel: 'gitmcp',
1111
serverUrl: 'https://gitmcp.io/openai/codex',
12-
requireApproval: 'never',
1312
}),
1413
],
1514
});

packages/agents-core/src/tool.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,10 @@ export function hostedMcpTool<Context = UnknownContext>(
136136
options: {
137137
serverLabel: string;
138138
serverUrl: string;
139+
allowedTools?: string[] | { toolNames?: string[] };
140+
headers?: Record<string, string>;
139141
} & (
140-
| { requireApproval: never }
142+
| { requireApproval?: never }
141143
| { requireApproval: 'never' }
142144
| {
143145
requireApproval:
@@ -151,20 +153,25 @@ export function hostedMcpTool<Context = UnknownContext>(
151153
),
152154
): HostedMCPTool<Context> {
153155
const providerData: ProviderData.HostedMCPTool<Context> =
156+
typeof options.requireApproval === 'undefined' ||
154157
options.requireApproval === 'never'
155158
? {
156159
type: 'mcp',
157160
server_label: options.serverLabel,
158161
server_url: options.serverUrl,
159162
require_approval: 'never',
163+
allowed_tools: toMcpAllowedToolsFilter(options.allowedTools),
164+
headers: options.headers,
160165
}
161166
: {
162167
type: 'mcp',
163168
server_label: options.serverLabel,
164169
server_url: options.serverUrl,
170+
allowed_tools: toMcpAllowedToolsFilter(options.allowedTools),
171+
headers: options.headers,
165172
require_approval:
166173
typeof options.requireApproval === 'string'
167-
? options.requireApproval
174+
? 'always'
168175
: buildRequireApproval(options.requireApproval),
169176
on_approval: options.onApproval,
170177
};
@@ -595,3 +602,15 @@ function buildRequireApproval(requireApproval: {
595602
}
596603
return result;
597604
}
605+
606+
function toMcpAllowedToolsFilter(
607+
allowedTools: string[] | { toolNames?: string[] } | undefined,
608+
): { tool_names: string[] } | undefined {
609+
if (typeof allowedTools === 'undefined') {
610+
return undefined;
611+
}
612+
if (Array.isArray(allowedTools)) {
613+
return { tool_names: allowedTools };
614+
}
615+
return { tool_names: allowedTools?.toolNames ?? [] };
616+
}

packages/agents-core/src/types/providerData.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export type HostedMCPTool<Context = UnknownContext> = {
88
type: 'mcp';
99
server_label: string;
1010
server_url: string;
11+
allowed_tools?: string[] | { tool_names: string[] };
12+
headers?: Record<string, string>;
1113
} & (
1214
| { require_approval?: 'never'; on_approval?: never }
1315
| {

packages/agents-openai/src/openaiResponsesModel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ function converTool<_TContext = unknown>(
191191
type: 'mcp',
192192
server_label: tool.providerData.server_label,
193193
server_url: tool.providerData.server_url,
194+
allowed_tools: tool.providerData.allowed_tools,
195+
headers: tool.providerData.headers,
194196
require_approval: convertMCPRequireApproval(
195197
tool.providerData.require_approval,
196198
),

0 commit comments

Comments
 (0)