Skip to content

Add MCP server tool filtering support to agents-js #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 28, 2025

Conversation

vrtnis
Copy link
Contributor

@vrtnis vrtnis commented Jul 1, 2025

Hey all - this PR brings a new tool filtering feature to our MCP integrations. This resolves #162 based on openai/openai-agents-python#861

You can now:

  1. Use createStaticToolFilter for quick allow/block lists

  2. Provide a custom filter function to make dynamic decisions based on runContext

  3. Updated core API so getAllTools now accepts your runContext, ensuring filters are applied correctly

  4. Documentation enhancements in docs/guides/mcp.mdx

  5. New example (examples/mcp/tool-filter-example.ts) to demonstrate both static and dynamic filtering

  6. Comprehensive tests covering static lists, callable filters, multi-server hierarchies, and cache interactions

All tests pass and you can try it out by pnpm -F mcp start:tool-filter

Copy link

changeset-bot bot commented Jul 1, 2025

🦋 Changeset detected

Latest commit: 161965f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@openai/agents-realtime Patch
@openai/agents-core Patch
@openai/agents Patch
@openai/agents-openai Patch
@openai/agents-extensions Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dkundel-openai
Copy link
Collaborator

@seratch can you review please?

Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sending this! I haven't verified the actual behavior yet but let me share a few quick comments

@vrtnis
Copy link
Contributor Author

vrtnis commented Jul 10, 2025

thanks for the comments, @seratch! esp. the point about moving filtering logic that makes sense for keeping the server implementation focused on transport.
i’ve pushed an update that moves filtering into the agent and runner layer, where it can be handled with proper context. look forward to your feedback!

@vrtnis
Copy link
Contributor Author

vrtnis commented Jul 11, 2025

Thanks @seratch. That makes sense and i’ve removed the runContext and agent from the call to underlying.listTools(), so that now filtering happens entirely in getAllMcpFunctionTools() on the agent side.

Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, one more request from me

@vrtnis vrtnis force-pushed the feat/mcp-tool-filtering-js branch from 4dce2d5 to 47ae347 Compare July 15, 2025 17:53
Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did thorough review and I found your current implementation actually does nothing for allowing/blocking tools. I've implemented draft version of change here: seratch@73eb37a Hope sharing this clarifies things!

console.log('\nAttempting to write a file (should be blocked):');
result = await run(
agent,
'Create a file named test.txt with the text "hello"',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently this is blocked either way because the mcp server has the access only to sample_files/

my diff changed this as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved through merge of 73eb37a, example updated accordingly. Also, e4ba592 explicitly lists sample_files to allow listing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for sharing your draft, @seratch! You’re absolutely right, my plumbing additions never actually invoked the filter, so allow/block lists weren’t doing anything.

I’ve since merged your implementation from 73eb37a and used that as the foundation. Appreciate the clarity your diff brought to this.

One question: should we also update the test to explicitly include toolUseBehavior: 'stop_on_first_tool' in the agent config? That setting ensures the run exits immediately with a "Tool \"write_file\" is blocked by MCP filter." error rather than continuing or looping, which might make the filter behavior clearer and more predictable in test output.

happy to add that if helpful!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out. I agree the agent should behave in the way you mentioned for the scenario. Adding test patterns would be appreciated!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added an integration test, i.e., mcpToolFilter.integration.test.ts that spins up the stub FS server and verifies that list_directory (allowed) works and write_file (blocked) gets immediately rejected with the expected message using toolUseBehavior: 'stop_on_first_tool'.

I also expanded the original unit tests to cover no filter, allow-only, block-only, async filters, thrown errors, and cache invalidation. This should give us better coverage across edge cases.

Lastly, I added a script to package.json so the example can now be run via pnpm examples:tool-filter.

Thoughts? Let me know if we should have anything else covered!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed that CI had failed on the merge commit (b5ff9ac) due to a type issue with modelResponses in the integration test. I fixed it by adding the correct ModelResponse[] type. It should be good now.

@vrtnis vrtnis force-pushed the feat/mcp-tool-filtering-js branch from b73a090 to 5ab34ae Compare July 25, 2025 01:56
Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes are now all good, but there are a few things to adjust 🙏

You can restrict which tools are exposed from each server. Pass either a static filter
using `createMCPToolStaticFilter` or a custom function:

```ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We consistently use compiled code snippets in docs. can you do this?

  • Add examples/docs/mcp/tool-filter.ts, which compiles and works
  • Add import stdioExample from '../../../../../examples/docs/mcp/tool-filter.ts?raw'; and use it here

If you're unsure or don't have time for this, please just remove this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good point. I've added the example as suggested. Confirmed that it compiles and works (screenshot attached).
screenshot00-28-00

@vrtnis vrtnis force-pushed the feat/mcp-tool-filtering-js branch from bb41f61 to 161965f Compare July 28, 2025 07:26
Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@seratch seratch merged commit 08dd469 into openai:main Jul 28, 2025
5 checks passed
@seratch
Copy link
Member

seratch commented Jul 28, 2025

@vrtnis Thank you so much for working on this PR 👏

@vrtnis
Copy link
Contributor Author

vrtnis commented Jul 28, 2025

Thanks @seratch, appreciate the thoughtful reviews and guidance throughout. Learned a lot working through this one! 🙌

vrtnis added a commit to vrtnis/openai-agents-js that referenced this pull request Jul 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add tool filter to MCP support
4 participants