Skip to content

refactor(MCP): Replace MCPRouter with FastMCP Proxy #8877

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 21 commits into from
Jun 8, 2025

Conversation

xingyaoww
Copy link
Collaborator

@xingyaoww xingyaoww commented Jun 3, 2025

  • This change is worth documenting at https://docs.all-hands.dev/
  • Include this change in the Release Notes. If checked, you must provide an end-user friendly description for your change below

End-user friendly description of the problem this fixes or functionality this introduces.


Summarize what the PR does, explaining any non-trivial design decisions.

Replace MCPRouter with FastMCP Proxy for better reliability and support for streamable HTTP requests from latest MCP protocol (#8864)

This PR refactors the MCP Proxy implementation in the action execution server to use a dedicated MCPProxyManager class. The implementation simplifies the code by:

  1. Extracting MCP Proxy logic to a separate module (openhands/runtime/mcp/proxy/)
  2. Maintaining configuration in-memory instead of using file-based approach (removing MCP_CONFIG_PATH)
  3. Improving error handling and logging
  4. Providing a cleaner API for mounting and updating MCP tools

Link of any specific issues this addresses:


To run this PR locally, use the following command:

docker run -it --rm   -p 3000:3000   -v /var/run/docker.sock:/var/run/docker.sock   --add-host host.docker.internal:host-gateway   -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:d2943d3-nikolaik   --name openhands-app-d2943d3   docker.all-hands.dev/all-hands-ai/openhands:d2943d3

@iSevenDays
Copy link
Contributor

+1 I hope this PR can be merged quickly, as I'm having issues related to MCP reliability

xingyaoww and others added 4 commits June 3, 2025 14:16
- Created new MCPProxyManager class to encapsulate proxy functionality
- Removed file-based configuration in favor of in-memory configuration
- Updated action_execution_server.py to use the new MCPProxyManager
- Added comprehensive documentation for the new module
- Improved error handling and logging
@xingyaoww
Copy link
Collaborator Author

@OpenHands I got the following error when launching the test

2025-06-06 17:33:36 21:33:36 - openhands:DEBUG: action_execution_server.py:377 - Bash init commands completed
2025-06-06 17:33:36 21:33:36 - openhands:DEBUG: action_execution_server.py:304 - Runtime client initialized.
2025-06-06 17:33:36 21:33:36 - openhands:INFO: action_execution_server.py:666 - ActionExecutor initialized.
2025-06-06 17:33:36 21:33:36 - openhands:INFO: action_execution_server.py:676 - Initializing MCP Proxy Manager...
2025-06-06 17:33:36 21:33:36 - openhands.runtime.mcp.proxy.manager:INFO: manager.py:60 - Initializing FastMCP Proxy 'OpenHandsActionExecutionProxy'...
2025-06-06 17:33:36 ERROR: Traceback (most recent call last):
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/starlette/routing.py", line 692, in lifespan
2025-06-06 17:33:36 async with self.lifespan_context(app) as maybe_state:
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/micromamba/envs/openhands/lib/python3.12/contextlib.py", line 210, in aenter
2025-06-06 17:33:36 return await anext(self.gen)
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/code/openhands/runtime/action_execution_server.py", line 686, in lifespan
2025-06-06 17:33:36 mcp_proxy_manager.initialize()
2025-06-06 17:33:36 File "/openhands/code/openhands/runtime/mcp/proxy/manager.py", line 63, in initialize
2025-06-06 17:33:36 self.proxy = FastMCP.as_proxy(
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/fastmcp/server/server.py", line 1309, in as_proxy
2025-06-06 17:33:36 client = Client(backend)
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/fastmcp/client/client.py", line 150, in init
2025-06-06 17:33:36 self.transport = cast(ClientTransportT, infer_transport(transport))
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/fastmcp/client/transports.py", line 883, in infer_transport
2025-06-06 17:33:36 inferred_transport = MCPConfigTransport(config=transport)
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/fastmcp/client/transports.py", line 732, in init
2025-06-06 17:33:36 config = MCPConfig.from_dict(config)
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/fastmcp/utilities/mcp_config.py", line 77, in from_dict
2025-06-06 17:33:36 return cls(mcpServers=config.get("mcpServers", config))
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 File "/openhands/poetry/openhands-ai-5O4_aCHf-py3.12/lib/python3.12/site-packages/pydantic/main.py", line 253, in init
2025-06-06 17:33:36 validated_self = self.pydantic_validator.validate_python(data, self_instance=self)
2025-06-06 17:33:36 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-06 17:33:36 pydantic_core._pydantic_core.ValidationError: 2 validation errors for MCPConfig
2025-06-06 17:33:36 mcpServers.default.StdioMCPServer.command
2025-06-06 17:33:36 Field required [type=missing, input_value={}, input_type=dict]
2025-06-06 17:33:36 For further information visit https://errors.pydantic.dev/2.11/v/missing
2025-06-06 17:33:36 mcpServers.default.RemoteMCPServer.url
2025-06-06 17:33:36 Field required [type=missing, input_value={}, input_type=dict]
2025-06-06 17:33:36 For further information visit https://errors.pydantic.dev/2.11/v/missing
2025-06-06 17:33:36
2025-06-06 17:33:36 ERROR: Application startup failed. Exiting.
2025-06-06 17:33:36 21:33:36 - openhands:DEBUG: browser_env.py:126 - SHUTDOWN recv, shutting down browser env...

Copy link

openhands-ai bot commented Jun 6, 2025

I'm on it! xingyaoww can track my progress at all-hands.dev

Copy link

openhands-ai bot commented Jun 6, 2025

I fixed the error you encountered when launching the test by addressing a configuration issue in the FastMCP integration.

The error was occurring because the MCPProxyManager class was initializing with an empty configuration dictionary that didn't meet FastMCP's requirements. The validation errors showed that either a StdioMCPServer with a 'command' field or a RemoteMCPServer with a 'url' field was required.

I modified the MCPProxyManager class to initialize with a valid StdioMCPServer configuration that includes:

  • A 'command' field set to 'python'
  • 'args' field set to ['-m', 'mcp.server']
  • 'env' field as an empty dictionary
  • 'transport' field set to 'stdio'

This change provides the required configuration structure that FastMCP expects, which should resolve the validation errors you were seeing.

I've committed this fix and pushed it to the 'refactor-mcprouter-to-fastmcp' branch, so the PR #8877 has been updated with this change.

@xingyaoww xingyaoww marked this pull request as ready for review June 8, 2025 14:58
@xingyaoww xingyaoww requested a review from malhotra5 June 8, 2025 18:32
Copy link
Contributor

@malhotra5 malhotra5 left a comment

Choose a reason for hiding this comment

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

LGTM!

We should also remove mcpm and mcp from poetry

FastMCP will handle the mcp dependency from now on, which should prevent dependabot conflicts

@xingyaoww xingyaoww enabled auto-merge (squash) June 8, 2025 21:23
Copy link

openhands-ai bot commented Jun 8, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • Run Python Unit Tests

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #8877

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

@xingyaoww xingyaoww merged commit d6d5499 into main Jun 8, 2025
18 checks passed
@xingyaoww xingyaoww deleted the refactor-mcprouter-to-fastmcp branch June 8, 2025 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants