mirror of
https://github.com/mcp-use/mcp-use.git
synced 2026-09-14 18:06:01 +08:00
b45d9663ec
* fix(python): expose client capabilities to MCP servers Add list_roots_callback support to Python connectors to properly advertise the roots capability during MCP initialization handshake. Previously, the Python library was not exposing any client capabilities because the list_roots_callback was not being passed to ClientSession. This fix ensures the roots capability is always advertised, bringing the Python library in line with the TypeScript implementation. Changes: - Add roots and list_roots_callback params to BaseConnector - Add get_roots() and set_roots() methods for managing roots - Pass list_roots_callback to ClientSession in all connectors - Export Root type from connectors module - Update unit tests to expect list_roots_callback parameter Closes MCP-1063 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(python): add roots and list_roots_callback params to connectors - Add roots and list_roots_callback parameters to StdioConnector, HttpConnector, and SandboxConnector constructors - Add comprehensive unit tests for client capabilities exposure - Tests verify roots capability, get_roots(), set_roots(), and that all callbacks are correctly passed to ClientSession 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: fix import sorting and update API documentation - Fix import sorting in test_client_capabilities.py (ruff) - Regenerate API documentation for updated connector classes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(python): add list_roots() method to server Context Allow MCP servers to request the list of roots from connected clients via ctx.list_roots(). This follows the same pattern as ctx.sample() and ctx.elicit() for server-to-client requests. * feat(python): add roots params to MCPClient and config - Add roots and list_roots_callback parameters to MCPClient.__init__, from_dict(), and from_config_file() methods - Update create_connector_from_config() to pass roots params to all connector types (Stdio, HTTP, Sandbox) - Allows clients to configure roots at the MCPClient level and have them propagate to all sessions * test(python): add get_client_roots tool to primitive server Add a tool that demonstrates the roots capability by requesting and returning the list of roots from the connected client. Used for integration testing of the roots feature. * test(python): add integration tests for roots capability Add comprehensive integration tests for the roots feature: - test_roots_capability: Verify server can request/receive roots - test_roots_empty_by_default: Verify empty roots when not provided - test_roots_with_custom_callback: Verify custom callback precedence - test_set_roots_updates_server_view: Verify dynamic root updates * test(python): update unit tests for roots parameters Update mock assertions in test_client.py to expect the new roots and list_roots_callback parameters in create_connector_from_config calls. * ci(python): add roots to primitive tests and README badge - Add roots to CI workflow primitive test matrix - Add roots to PR comment report primitives list - Add Roots badge to README Primitives row * feat(docs): enhance MCP client and server documentation for roots feature - Added `roots` and `list_roots_callback` parameters to MCP client initialization documentation. - Updated `create_connector_from_config` documentation to include new parameters. - Introduced `list_roots` method documentation in server context, detailing its usage and return values. - Improved overall clarity and completeness of API reference for better developer guidance. * feat(python): add get_client_roots tool to context example - Introduced a new tool, `get_client_roots`, to the context example, demonstrating how to retrieve and display the list of roots exposed by the client. - Updated documentation to include the new tool and its functionality, enhancing the example's coverage of context features. * feat(docs): add roots documentation for client and server - Introduced new documentation for the `roots` feature, detailing how clients can expose file system roots to MCP servers and how servers can access these roots. - Added examples for configuring roots in the MCP client and using the `list_roots()` method in the server context. - Enhanced overall clarity and usability of the documentation to support developers in implementing the roots functionality. --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: pietrozullo <pietro.zullo@gmail.com>
143 lines
5.2 KiB
Python
143 lines
5.2 KiB
Python
"""
|
|
Configuration loader for MCP session.
|
|
|
|
This module provides functionality to load MCP configuration from JSON files.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from mcp.client.session import ElicitationFnT, ListRootsFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
|
|
from mcp.types import Root
|
|
|
|
from mcp_use.client.connectors.base import BaseConnector
|
|
from mcp_use.client.connectors.http import HttpConnector
|
|
from mcp_use.client.connectors.sandbox import SandboxConnector, SandboxOptions
|
|
from mcp_use.client.connectors.stdio import StdioConnector
|
|
from mcp_use.client.connectors.utils import is_stdio_server
|
|
from mcp_use.client.connectors.websocket import WebSocketConnector
|
|
from mcp_use.client.middleware import Middleware
|
|
from mcp_use.telemetry.telemetry import Telemetry
|
|
|
|
_telemetry = Telemetry()
|
|
|
|
|
|
def load_config_file(filepath: str) -> dict[str, Any]:
|
|
"""Load a configuration file.
|
|
|
|
Args:
|
|
filepath: Path to the configuration file
|
|
|
|
Returns:
|
|
The parsed configuration
|
|
"""
|
|
with open(filepath) as f:
|
|
return json.load(f)
|
|
|
|
|
|
def create_connector_from_config(
|
|
server_config: dict[str, Any],
|
|
sandbox: bool = False,
|
|
sandbox_options: SandboxOptions | None = None,
|
|
sampling_callback: SamplingFnT | None = None,
|
|
elicitation_callback: ElicitationFnT | None = None,
|
|
message_handler: MessageHandlerFnT | None = None,
|
|
logging_callback: LoggingFnT | None = None,
|
|
middleware: list[Middleware] | None = None,
|
|
verify: bool | None = True,
|
|
roots: list[Root] | None = None,
|
|
list_roots_callback: ListRootsFnT | None = None,
|
|
) -> BaseConnector:
|
|
"""Create a connector based on server configuration.
|
|
This function can be called with just the server_config parameter:
|
|
create_connector_from_config(server_config)
|
|
Args:
|
|
server_config: The server configuration section
|
|
sandbox: Whether to use sandboxed execution mode for running MCP servers.
|
|
sandbox_options: Optional sandbox configuration options.
|
|
sampling_callback: Optional sampling callback function.
|
|
Returns:
|
|
A configured connector instance
|
|
"""
|
|
|
|
# Stdio connector (command-based)
|
|
if is_stdio_server(server_config) and not sandbox:
|
|
_telemetry.track_connector_init(
|
|
connector_type="stdio",
|
|
server_command=server_config["command"],
|
|
server_args=server_config["args"],
|
|
public_identifier=f"stdio:{server_config['command']} {' '.join(server_config['args'])}",
|
|
)
|
|
return StdioConnector(
|
|
command=server_config["command"],
|
|
args=server_config["args"],
|
|
env=server_config.get("env", None),
|
|
sampling_callback=sampling_callback,
|
|
elicitation_callback=elicitation_callback,
|
|
message_handler=message_handler,
|
|
logging_callback=logging_callback,
|
|
middleware=middleware,
|
|
roots=roots,
|
|
list_roots_callback=list_roots_callback,
|
|
)
|
|
|
|
# Sandboxed connector
|
|
elif is_stdio_server(server_config) and sandbox:
|
|
_telemetry.track_connector_init(
|
|
connector_type="sandbox",
|
|
server_command=server_config["command"],
|
|
server_args=server_config["args"],
|
|
public_identifier=f"sandbox:{server_config['command']} {' '.join(server_config['args'])}",
|
|
)
|
|
return SandboxConnector(
|
|
command=server_config["command"],
|
|
args=server_config["args"],
|
|
env=server_config.get("env", None),
|
|
e2b_options=sandbox_options,
|
|
sampling_callback=sampling_callback,
|
|
elicitation_callback=elicitation_callback,
|
|
message_handler=message_handler,
|
|
logging_callback=logging_callback,
|
|
middleware=middleware,
|
|
roots=roots,
|
|
list_roots_callback=list_roots_callback,
|
|
)
|
|
|
|
# HTTP connector
|
|
elif "url" in server_config:
|
|
_telemetry.track_connector_init(
|
|
connector_type="http",
|
|
server_url=server_config["url"],
|
|
public_identifier=f"http:{server_config['url']}",
|
|
)
|
|
return HttpConnector(
|
|
base_url=server_config["url"],
|
|
headers=server_config.get("headers", None),
|
|
auth=server_config.get("auth", {}),
|
|
timeout=server_config.get("timeout", 5),
|
|
sse_read_timeout=server_config.get("sse_read_timeout", 60 * 5),
|
|
sampling_callback=sampling_callback,
|
|
elicitation_callback=elicitation_callback,
|
|
message_handler=message_handler,
|
|
logging_callback=logging_callback,
|
|
middleware=middleware,
|
|
verify=verify,
|
|
roots=roots,
|
|
list_roots_callback=list_roots_callback,
|
|
)
|
|
|
|
# WebSocket connector
|
|
elif "ws_url" in server_config:
|
|
_telemetry.track_connector_init(
|
|
connector_type="websocket",
|
|
server_url=server_config["ws_url"],
|
|
public_identifier=f"websocket:{server_config['ws_url']}",
|
|
)
|
|
return WebSocketConnector(
|
|
url=server_config["ws_url"],
|
|
headers=server_config.get("headers", None),
|
|
auth=server_config.get("auth", {}),
|
|
)
|
|
|
|
raise ValueError("Cannot determine connector type from config")
|