Source code for ralph.mcp.tools.bridge._registry

"""Tool registry builder for MCP bridge."""

from __future__ import annotations

from importlib import import_module
from typing import TYPE_CHECKING, cast

from ralph.mcp.protocol.capability_mapping import McpCapability
from ralph.mcp.tools.bridge._lazy_tool_handler import LazyToolHandler
from ralph.mcp.tools.bridge._specs_artifacts import artifact_specs
from ralph.mcp.tools.bridge._specs_file_list import file_list_specs
from ralph.mcp.tools.bridge._specs_file_read import file_read_specs
from ralph.mcp.tools.bridge._specs_file_write import file_write_specs
from ralph.mcp.tools.bridge._specs_git_exec import git_exec_specs
from ralph.mcp.tools.bridge._specs_web_media import web_media_specs
from ralph.mcp.tools.bridge._tool_bridge import ToolBridge
from ralph.mcp.tools.bridge._tool_definition import ToolDefinition
from ralph.mcp.tools.bridge._tool_metadata import ToolMetadata
from ralph.mcp.tools.bridge._upstream_proxy_handler import UpstreamProxyHandler

if TYPE_CHECKING:
    from ralph.config.mcp_models import McpConfig
    from ralph.mcp.tools.bridge._tool_spec import ToolSpec
    from ralph.mcp.upstream.registry import UpstreamRegistry


[docs] def tool_specs(mcp_config: McpConfig) -> tuple[ToolSpec, ...]: """Build the full ordered list of tool specifications for the MCP bridge.""" specs: list[ToolSpec] = [] specs.extend(file_read_specs()) specs.extend(file_list_specs()) specs.extend(file_write_specs()) specs.extend(git_exec_specs()) specs.extend(artifact_specs()) specs.extend(web_media_specs(mcp_config)) return tuple(specs)
def _attach_upstream_registry(bridge: ToolBridge, upstream_registry: UpstreamRegistry) -> None: for proxied_tool in upstream_registry.tool_definitions(): metadata = ToolMetadata( definition=ToolDefinition( name=proxied_tool.alias, description=proxied_tool.tool.description, input_schema=proxied_tool.tool.input_schema, ), required_capability=McpCapability.UPSTREAM_TOOL_USE, ) handler = UpstreamProxyHandler( alias=proxied_tool.alias, upstream_registry=upstream_registry, ) bridge.register(metadata, handler)
[docs] def build_ralph_tool_registry( session: object, workspace: object, *, upstream_registry: UpstreamRegistry | None = None, mcp_config: McpConfig | None = None, ) -> ToolBridge: """Build the default Ralph MCP tool registry.""" mcp_config_cls = cast("type[McpConfig]", import_module("ralph.config.mcp_models").McpConfig) mcp_cfg = mcp_config or mcp_config_cls() bridge = ToolBridge(session=session) for spec in tool_specs(mcp_cfg): is_websearch = ( spec.module_name == "ralph.mcp.tools.websearch" and spec.handler_name == "handle_web_search" ) is_webvisit = ( spec.module_name == "ralph.mcp.tools.webvisit" and spec.handler_name == "handle_visit_url" ) is_read_image = ( spec.module_name == "ralph.mcp.tools.workspace" and spec.handler_name == "handle_read_image" ) is_read_media = ( spec.module_name == "ralph.mcp.tools.workspace" and spec.handler_name == "handle_read_media" ) if is_websearch: bridge.register( spec.metadata, LazyToolHandler( module_name=spec.module_name, handler_name=spec.handler_name, session=session, workspace=workspace, extra_kwargs={"web_search_config": mcp_cfg.web_search}, ), ) elif is_webvisit: bridge.register( spec.metadata, LazyToolHandler( module_name=spec.module_name, handler_name=spec.handler_name, session=session, workspace=workspace, extra_kwargs={"web_visit_config": mcp_cfg.web_visit}, ), ) elif is_read_image or is_read_media: bridge.register( spec.metadata, LazyToolHandler( module_name=spec.module_name, handler_name=spec.handler_name, session=session, workspace=workspace, extra_kwargs={"max_inline_bytes": mcp_cfg.media.max_inline_bytes}, ), ) else: bridge.register_spec(spec, session=session, workspace=workspace) if upstream_registry is not None: _attach_upstream_registry(bridge, upstream_registry) return bridge