Skip to content

MCP interop

Tools from external Model Context Protocol servers plug straight into the registry — once registered they are ordinary ToolSpecs the worker/swarm call with no graph changes.

The core is dependency-free and testable offline via FakeMcpClient; the real stdio transport (StdioMcpClient) needs the [mcp] extra.

Register from code

from riptide_watergraph import register_mcp_tools, default_registry
from riptide_watergraph.mcp.stdio import StdioMcpClient   # pip install "riptide-watergraph[mcp]"

registry = default_registry()
client = StdioMcpClient(command="npx",
                        args=["-y", "@modelcontextprotocol/server-filesystem", "/data"])
await register_mcp_tools(registry, client, prefix="fs.")   # fs.read_file, fs.write_file, ...

Read-only MCP tools run inline (and in parallel in swarm mode); the rest are side_effecting and route through the human-approval gate. The prefix namespaces them so they never collide with local tools.

Connect from the Studio (gated + allowlisted)

The Studio's MCP Servers view turns the catalog into live tools without code — but only when RIPTIDE_ENABLE_MCP_CONNECT=1 and the target server is pre-declared in the allowlist. The browser can never launch an arbitrary command.

export RIPTIDE_ENABLE_MCP_CONNECT=1
export RIPTIDE_MCP_SERVERS='[{"name":"fs","command":"npx",
  "args":["-y","@modelcontextprotocol/server-filesystem","."],"prefix":"fs."}]'
riptide serve        # MCP Servers > Connect → fs.* tools appear everywhere; Disconnect removes them

Connected tools join a dynamic-spec store that default_registry() appends, so they persist across Chat, Playground, Workflows and the Tool Runner.

Endpoint Purpose
GET /api/mcp list allowlist entries + connection state
POST /api/mcp/connect {name} connect (403 if gate off, 404 if not allowlisted)
POST /api/mcp/disconnect {name} disconnect + unregister the tools

See examples/mcp_connect.py for an offline end-to-end demo with FakeMcpClient.