Skip to content

Commit a92990b

Browse files
committed
docs(agents-core): document MCP structuredContent; test(mcp): add structured content tests and update stubs; chore(changeset): minor bump
1 parent 5ac885c commit a92990b

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@openai/agents-core': minor
3+
---
4+
5+
feat(mcp): add structuredContent support behind `useStructuredContent`; return full CallToolResult from `callTool`
6+
7+
- `MCPServer#callTool` now returns the full `CallToolResult` (was `content[]`), exposing optional `structuredContent`.
8+
- Add `useStructuredContent` option to MCP servers (stdio/streamable-http/SSE), default `false` to avoid duplicate data by default.
9+
- When enabled, function tool outputs include `structuredContent` (or return it alone when no `content`).
10+
11+
Notes
12+
13+
- Type-only breaking change for direct `callTool` consumers: use `result.content` where arrays were expected.
14+
- Behavior matches Python SDK feature (openai-agents-python#1150) while keeping JS outputs ergonomic (objects/arrays, no JSON stringify/parse overhead).

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ describe('MCP structuredContent handling', () => {
6464
false,
6565
);
6666

67-
const out = await tool.invoke({} as any, {});
67+
const out = await tool.invoke({} as any, '{}');
6868
// when not using structured content, return the single content object
6969
expect(out).toEqual({ type: 'text', text: 'hello' });
7070
});
7171

72-
it('includes structuredContent when enabled: single content -> newline-concatenated string', async () => {
72+
it('includes structuredContent when enabled: single content -> array with structuredContent appended', async () => {
7373
const server = new StubServer(
7474
's',
7575
[
@@ -106,8 +106,8 @@ describe('MCP structuredContent handling', () => {
106106
false,
107107
);
108108

109-
const out = await tool.invoke({} as any, {});
110-
expect(out).toBe('{"type":"text","text":"hello"}\n{"foo":1}');
109+
const out = await tool.invoke({} as any, '{}');
110+
expect(out).toEqual([{ type: 'text', text: 'hello' }, { foo: 1 }]);
111111
});
112112

113113
it('includes structuredContent when enabled: no content -> structuredContent only', async () => {
@@ -147,7 +147,7 @@ describe('MCP structuredContent handling', () => {
147147
false,
148148
);
149149

150-
const out = await tool.invoke({} as any, {});
150+
const out = await tool.invoke({} as any, '{}');
151151
expect(out).toEqual({ foo: 1 });
152152
});
153153

@@ -191,7 +191,7 @@ describe('MCP structuredContent handling', () => {
191191
false,
192192
);
193193

194-
const out = await tool.invoke({} as any, {});
194+
const out = await tool.invoke({} as any, '{}');
195195
expect(out).toEqual([
196196
{ type: 'text', text: 'a' },
197197
{ type: 'text', text: 'b' },

packages/agents-core/test/mcpToolFilter.integration.test.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,25 @@ class StubFilesystemServer extends NodeMCPServerStdio {
6060
async callTool(name: string, args: any) {
6161
const blocked = (this.toolFilter as any)?.blockedToolNames ?? [];
6262
if (blocked.includes(name)) {
63-
return [
64-
{ type: 'text', text: `Tool "${name}" is blocked by MCP filter` },
65-
];
63+
return {
64+
content: [
65+
{ type: 'text', text: `Tool "${name}" is blocked by MCP filter` },
66+
],
67+
} as any;
6668
}
6769
if (name === 'list_directory') {
6870
const files = fs.readdirSync(this.dir);
69-
return [{ type: 'text', text: files.join('\n') }];
71+
return { content: [{ type: 'text', text: files.join('\n') }] } as any;
7072
}
7173
if (name === 'read_file') {
7274
const text = fs.readFileSync(path.join(this.dir, args.path), 'utf8');
73-
return [{ type: 'text', text }];
75+
return { content: [{ type: 'text', text }] } as any;
7476
}
7577
if (name === 'write_file') {
7678
fs.writeFileSync(path.join(this.dir, args.path), args.text, 'utf8');
77-
return [{ type: 'text', text: 'ok' }];
79+
return { content: [{ type: 'text', text: 'ok' }] } as any;
7880
}
79-
return [];
81+
return { content: [] } as any;
8082
}
8183
}
8284

0 commit comments

Comments
 (0)