For the complete documentation index, see llms.txt. This page is also available as Markdown.

MCP Registry (src/openhuman/mcp_registry/)

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 t

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::tools::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/config_servers/ + src/openhuman/mcp/http_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::http_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 http_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::http_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 in TOML).

connections.rs

Global in-process connection registry. Wraps crate::openhuman::mcp::config_servers::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:

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::config_servers::McpStdioClient: the actual stdio transport.

  • crate::openhuman::tools::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 themcp_setupsub-agent (orchestrator delegatesetup_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/config_servers/ + src/openhuman/mcp/http_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.

Last updated