-
Notifications
You must be signed in to change notification settings - Fork 606
feat(mcp): Implement basic support for Tasks #1475
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
base: main
Are you sure you want to change the base?
Conversation
14da5f4 to
0411e91
Compare
0411e91 to
17d0842
Compare
17d0842 to
a26b769
Compare
a26b769 to
4d1b95c
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
4d1b95c to
4d1af11
Compare
Implements client support for MCP Tasks via an adapter model that handles both tool execution modes identically. This can later be hooked into event handlers in a more intelligent way, but this unblocks support for simply invoking task-augmented tools. Keep error handling and edge case tests (timeout, failure status, config). Also remove unused create_tool_with_task_support helper and trim task_echo_server. Reduces PR diff from 1433 to 969 lines (under 1000 limit).
4d1af11 to
ac9577b
Compare
src/strands/tools/mcp/mcp_client.py
Outdated
|
|
||
| async def _list_tools_async() -> ListToolsResult: | ||
| return await cast(ClientSession, self._background_thread_session).list_tools(cursor=pagination_token) | ||
| async def _list_tools_and_cache_capabilities_async() -> ListToolsResult: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level comment
I think we should consider the experimental nature of tasks.
I am fine with the session.experimental.poll_task in the non-experimental strands.MCPClient.
But what feels strange to me is that this is not opt-in on behalf of the mcp client. Instead it seems that a Strands application could be automatically opted in to the experimental behavior because of a change made to a remote MCP server. For an experimental feature that feels strange. But want to hear your thoughts on how things like this have been rolled out for MCP in the past!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first time we've had a situation like this in MCP, so there's room for discussion on how we integrate this. My reasoning is just that it's better to be optimistic and elegantly handle errors than it is to force a break without the application opting into support. We can put this under some sort of option if you'd prefer the latter behavior, though.
My general opinion on this is that it should be handled as invisibly as possible, which is why the TS SDK wraps both task and non-task tool calls in the same callToolStream method, with the intent being that an SDK consumer would simply replace their callTool calls with callToolStream in one go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding "optimistic and elegantly handle errors than it is to force a break without the application opting into support." I definitely agree in principal. If a breaking change was made to MCP tasks how would that be surfaced on the capability negotiation?
Basically I want to tease out if a client is on v1 of tasks and a server switches to v2 of tasks, would v1 no-op here or would it attempt to use the feature and potentially fail? Basically I want to be careful since the SDKs MCP dependency isn't pinned
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends on the nature of the change - it likely wouldn't be communicated via capabilities (as capabilities themselves aren't versioned), so that could indeed cause problems depending on the client SDK version. While I don't anticipate us redesigning Tasks in a backwards-incompatible way at this point, it is possible that there could be some interplay between Tasks and the (probable) incoming new Streamable HTTP specs that could cause subtle issues. That would be a good argument in favor of putting this under an option.
I did forget that the MCP SDK version is unpinned however, I'll have to see if this even works on versions prior to November. That will definitely require some additional checks (though those ones can be automatic).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spoke with @zastrowm, I think opt in is going to be necessary. I think we can do per-feature experimental flags using some new dictionary on the MCPClient class like
experimental: {
tasks: bool
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implemented in the latest commit - I moved the other new task-specific options into a new dict on experimental.tasks, too.
Description
Implements client support for MCP Tasks via an adapter model that handles both tool execution modes identically. This can later be hooked into event handlers in a more intelligent way, but this unblocks support for simply invoking task-augmented tools.
Note that unlike strands-agents/sdk-typescript#357, this PR handles the capability/executionMode logic explicitly, as the MCP Python SDK's implementation of Tasks does not encapsulate that logic, unlike the MCP TS SDK.
Related Issues
#1260
Documentation PR
N/A
Type of Change
New feature
Testing
How have you tested the change? Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli
hatch run prepareChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.