Files

9.2 KiB

description, icon
description icon
The dynamic, user-facing side of MCP-client support: discover servers on Smithery and the official MCP registry, persist installs to SQLite, supervise local-spawn subprocess lifecycle, surface their tools to agents via the unified tool registry. plug

MCP Registry (src/openhuman/mcp_registry/)

src/openhuman/mcp_registry/ is the dynamic, user-facing half of OpenHuman's Model Context Protocol client support. It lets a user browse the supported upstream registries (Smithery and the official modelcontextprotocol registry), install a chosen server, persist that choice to SQLite, and (for servers launched as local subprocesses or HTTP-remote endpoints) supervise the connection lifecycle. Installed servers' tools are surfaced to agents via the unified tool registry (crate::openhuman::tool_registry).

Naming note: the Rust module path is mcp_registry, but the RPC namespace and on-disk SQLite filename are still mcp_clients for backward compatibility with existing frontend code and stored user state. Grep both names when chasing call sites.

This module is paired with src/openhuman/mcp_client/: the transport library (HTTP + stdio primitives) plus the static, config-declared server set read from [[mcp_client.servers]] in config.toml. Agents reach that static set through generic bridge tools. The static set is intentionally separate from this dynamic registry; both kinds will eventually share the transport primitives from mcp_client.

                 ┌───────────────────────────────────────────────┐
   Registries ───► registries/ + registry.rs (10-min SQLite cache)│
                 └────────────────────┬──────────────────────────┘
                                      │ browse / install
                                      ▼
                          ┌──────────────────────┐
   Frontend (Skills UI) ─►│  ops.rs / schemas.rs │  RPC controllers
                          └──────────┬───────────┘
                                     │
                                     ▼
                          ┌──────────────────────┐
                          │      store.rs        │  mcp_clients.db (SQLite)
                          │  InstalledServer rows│
                          └──────────┬───────────┘
                                     │ at boot
                                     ▼
                          ┌──────────────────────┐
                          │       boot.rs        │  spawn_installed_servers
                          └──────────┬───────────┘
                                     │ for each local-spawn
                                     ▼
                          ┌──────────────────────┐
                          │   connections.rs     │  wraps mcp_client::
                          │  (global registry)   │  McpStdioClient
                          └──────────┬───────────┘
                                     │ surfaces tools to
                                     ▼
                          tool_registry (agents)

Server transport model

An InstalledServer carries a transport: Transport discriminator (types.rs) with two variants:

  • Stdio: a local subprocess launched by npx, uvx, or a direct binary (see types::CommandKind), speaking stdio JSON-RPC.
  • HttpRemote { url }: a hosted server (the majority of what Smithery lists), dialled over streamable HTTP by mcp_client::McpHttpClient.

connections.rs dispatches on the transport. Both the manual install dialog (mcp_clients_install) and the setup-agent path (mcp_setup_install_and_connect) pick the best connection via setup_ops::pick_connection (published stdio → any stdio → published http_remote → any http_remote) and build the transport with setup_ops::build_install_transport, so the two paths behave identically.

Boot-time spawn

boot::spawn_installed_servers is called from bootstrap_core_runtime so every installed server is connected as soon as the core comes up. Errors are logged per-server and never block boot; a broken MCP install should not gate the desktop app starting. The lifecycle log subscriber (bus::init) is registered alongside the other domain subscribers in register_domain_subscribers so those connect events are observed.

Layout

Path Role
types.rs Data structures: InstalledServer, McpTool, ConnStatus, Smithery DTOs, etc.
store.rs SQLite persistence: mcp_clients.db, CRUD over InstalledServer rows.
registry.rs Smithery HTTP client with a 10-minute SQLite cache so re-browsing doesn't hammer the upstream registry.
registries/ Adapters for the upstream registries this code can browse: Smithery (smithery.rs) + the official modelcontextprotocol registry (mcp_official.rs). Each reads optional auth config-first with an env-var fallback (mcp_client.registry_auth).
connections.rs Global in-process connection registry. Wraps crate::openhuman::mcp_client::McpStdioClient (there is no separate stdio client implementation here).
boot.rs Boot-time spawn (spawn_installed_servers) called from bootstrap_core_runtime.
setup.rs / setup_ops.rs "Setup agent" support: the small agent that walks a user through configuring a freshly installed server (env vars, secrets, first connect).
ops.rs RPC handler implementations (install, uninstall, list, browse, enable / disable, etc.).
schemas.rs Controller schemas + handler dispatch. Re-exported from mod.rs as all_mcp_registry_controller_schemas / all_mcp_registry_registered_controllers.
bus.rs DomainEvent subscriber for lifecycle logging.

Public surface

The exports from mod.rs are intentionally narrow:

pub use schemas::{
    all_controller_schemas as all_mcp_registry_controller_schemas,
    all_registered_controllers as all_mcp_registry_registered_controllers,
    schemas as mcp_registry_schemas,
};

pub use types::{ConnStatus, InstalledServer, McpTool};

Everything else (boot, bus, connections, store, setup, setup_ops) is pub mod for in-crate callers but not re-exported.

Calls into

  • crate::openhuman::mcp_client::McpStdioClient: the actual stdio transport.
  • crate::openhuman::tool_registry: installed servers' tools land here so agents see them alongside native tools.
  • memory_store / workspace SQLite, for mcp_clients.db persistence.
  • Smithery.ai HTTP, for registry browsing.

Called by

  • bootstrap_core_runtime (via boot::spawn_installed_servers).
  • Frontend Skills UI: the MCP tab at /skills?tab=mcp (McpServersTab) dispatches through ops.rs over the openhuman.mcp_clients_* RPC namespace: browse, install (auto-connects), connect/disconnect, status, tool_call, update_env (reconfigure + reconnect), and registry_settings_get / registry_settings_set (Smithery / official-registry credentials; secret values are write-only). The agent-native flow uses openhuman.mcp_setup_* via the mcp_setup sub-agent (orchestrator delegate setup_mcp_server).
  • The setup agent in setup_ops.rs, for first-connect onboarding.

Tests

Unit tests are co-located inline under #[cfg(test)] blocks in store.rs, connections.rs, and setup.rs. There is no dedicated *_tests.rs sibling per file (the convention in this domain is inline).

  • mcp_registry/mod.rs: the authoritative rustdoc this page mirrors.
  • src/openhuman/mcp_client/: the transport library + static config-declared server set.
  • Agent Harness: how the agent ends up calling MCP tools through tool_registry.
  • Architecture overview: where this fits in the wider system.