feat: redo tool filtering for better tests#457
Conversation
|
For team members: test commit |
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
| # Tool must not have any excluded tags | ||
| if self.exclude_tags and self.exclude_tags.intersection(tool_tags): | ||
| # Tool must have one of the required tags | ||
| if self.tags and self.tags.isdisjoint(tool_tags): |
There was a problem hiding this comment.
I like the simplicity, much easier to understand than the old include/exclude kwargs stuff! Just want to make sure I understand the logic correctly,I want to confirm
- self.tags = set() - Does this mean all tools get included?
- tool_tags = set() - Does this mean the tool gets excluded from everything?
There was a problem hiding this comment.
This part actually makes me confused a bit. self.tags is acting like an allow list when it contains a least one value, but when it's an empty set, it means no filtering just include any tools. Maybe it's just me. Anyway, since self.tags being an empty set is just never the case for now, we don't have to consider this edge case.
Jazzcort
left a comment
There was a problem hiding this comment.
Just left some of my thoughts. Everything looks good to me! Slick as always! 😁
|
|
||
|
|
||
| def _hide_app_tools_for_client(client_params: InitializeRequestParams): | ||
| # Versions of goose before 1.29.0 don't understand _meta.ui.visiblity, so would |
There was a problem hiding this comment.
Just a quick question here. So in FastMcp 3.x, if the tools is not listed in tools/list, it not callable with tools/call. 🤔
| return False | ||
|
|
||
| if self.mcp_apps: | ||
| if "mcp_apps_exclude" in component.tags: |
There was a problem hiding this comment.
Found a probably wrong documentation for "mcp_apps_exclude" in scripts/generate_tool_docs.py when I was confused about why we have both mcp_apps_exclude and mcp_apps_only, but after I rubbed my head around it now it make whole lots of sense. 😁
Probably wrong documentation
It should be (e.g. Goose Desktop, Claude Desktop ...etc.) right?
If yes, I can do a separate patch for this.
if "mcp_apps_only" in tool.tags:
notes.append("Only available with clients that support MCP apps (e.g. RHEL Lightspeed).")|
|
||
| The dynamic behavior is done *per call*, not per session, since that's more future-proof. | ||
| (Future MCP protocol versions will remove sessions entirely: | ||
| https://modelcontextprotocol.io/seps/2575-stateless-mcp). This means doing it ourselves |
There was a problem hiding this comment.
FastMcp already has the sessionless option for the http transport. I hope the change will be just making it the default setting in the future. Anyway, we can always do it ourselves. 😁
| # Tool must not have any excluded tags | ||
| if self.exclude_tags and self.exclude_tags.intersection(tool_tags): | ||
| # Tool must have one of the required tags | ||
| if self.tags and self.tags.isdisjoint(tool_tags): |
There was a problem hiding this comment.
This part actually makes me confused a bit. self.tags is acting like an allow list when it contains a least one value, but when it's an empty set, it means no filtering just include any tools. Maybe it's just me. Anyway, since self.tags being an empty set is just never the case for now, we don't have to consider this edge case.
125099c to
402cbac
Compare
|
For team members: test commit |
Just pushed a new version differing only in that def includes_tool(self, tool_tags: set[str]) -> bool:
# Tool must have one of the required tags
return not self.tags.isdisjoint(tool_tags)Hopefully everyone will be less confused now! |
Filtering tools at server startup made it hard to test the effects of CONFIG.toolset. Switch to a system where tools are completely filtered in the middleware. (Doing it at the session level would be possible, but the direction for future protocol versions of MCP is to remove sessions entirely) This allows making the tests for server.py more comprehensive and greatly reduces the amount of mocking necessary. * All tests for server.py are moved into a new test_server.py. * Instead of making "fixed" the default toolset for tools without a tag, fixed tools are tagged just like run_script tools are. * toolset.Toolset is modified to only have tags for inclusion rather than exclusion tags as well. * A new setup_client fixture is added that is more flexible than the old mcp_client fixture - it's callable and the desired toolset and mcp-app support are passed in. * Our mcp-app HTML resource is properly filtered along with the tools.
402cbac to
9d705a3
Compare
|
For team members: test commit |
Filtering tools at server startup made it hard to test the effects of CONFIG.toolset. Switch to a system where tools are completely filtered in the middleware. (Doing it at the session level would be possible, but the direction for future protocol versions of MCP is to remove sessions entirely)
This allows making the tests for server.py more comprehensive and greatly reduces the amount of mocking necessary.
The end result is test coverage of server.py is increased from 70% => 95%.