How OpenHuman Integrates MCP Servers Using Static Config and Dynamic Registry Paths

OpenHuman treats MCP (Mini-Control-Plane) servers as first-class backends by merging a hard-coded static configuration loaded at boot time with a mutable SQLite-backed registry stored in the user workspace, creating a unified server catalog that supports both immutable defaults and runtime customization.

OpenHuman, developed by the tinyhumansai/openhuman repository, provides a dual-path discovery mechanism that ensures essential MCP services are available immediately upon startup while allowing users to register additional endpoints dynamically. This architecture separates immutable system defaults from user-specific configurations, enabling seamless integration of both built-in cloud services and custom self-hosted servers. Understanding how OpenHuman integrates MCP servers using static config and dynamic registry paths reveals a sophisticated balance between reliability and flexibility.

Static Configuration: Immutable Server Definitions

OpenHuman reads static MCP server definitions from the core configuration file through the parser implemented in src/openhuman/mcp/config.rs. During the boot sequence, the system searches for a TOML block named [[mcp_client.servers]], which contains hard-coded server entries that include a unique identifier, URL endpoint, and optional bearer token authentication.

Because these entries reside in the immutable core configuration, they are available before any user-specific workspace data loads, ensuring that critical infrastructure services remain reachable regardless of user state. The load_static_servers() function parses these definitions into McpServer structs, creating a baseline registry that guarantees production defaults are always present.


# ---------------------------------------------------------------------

# Example – Static MCP server entry in `config.toml`

# ---------------------------------------------------------------------

[[mcp_client.servers]]
id = "builtin-cloud"
url = "https://cloud.tinyhumans.ai/mcp"
bearer = "env:OPENHUMAN_CLOUD_TOKEN"

Dynamic Registry: Runtime Server Management

Complementing the static configuration, OpenHuman implements a dynamic registry in src/openhuman/mcp/registry.rs that persists MCP servers in a SQLite database located at ~/.openhuman/mcp_clients.db. This registry is managed by the McpServerRegistry struct, which exposes CRUD operations through RPC calls including mcp_add_server, mcp_remove_server, and mcp_list_servers.

Agents and users can register custom endpoints—such as self-hosted Smithery servers—at runtime without modifying the global configuration file. The system automatically reloads these entries on subsequent startups, enabling user-driven discovery of servers unknown at compile time while maintaining workspace-scoped isolation for security.

// ---------------------------------------------------------------------
// Example – Adding a server via the dynamic registry (via RPC)
// ---------------------------------------------------------------------
use openhuman_core::api::mcp::{AddServerRequest, AddServerResponse};

let req = AddServerRequest {
    id: "my‑custom‑mcp".into(),
    url: "https://mcp.mycompany.com/api".into(),
    bearer: Some("s3cr3t‑token".into()),
};
let resp: AddServerResponse = core_rpc_client
    .call("mcp_add_server", &req)
    .await?;   // registers the server in the SQLite DB

println!("Server added, now reachable as {}", resp.id);

How OpenHuman Merges Static and Dynamic Discovery Paths

The integration layer in src/openhuman/mcp/mod.rs orchestrates the convergence of both configuration sources during the boot process, ensuring a single source of truth for the entire system.

Boot-Time Loading Sequence

When the OpenHuman core initializes, it executes two distinct loading functions: load_static_servers() reads the TOML configuration block, while load_registry_servers() opens the SQLite database and reads persisted rows. Both functions return Vec<McpServer> collections that represent their respective configuration sources.

Registry Merging and Deduplication

The system concatenates the static and dynamic vectors, applies deduplication logic based on server ID to prevent conflicts, and stores the merged result in a global McpServerRegistry instance housed within the core's CoreContext. This unified registry serves as the authoritative catalog for all subsequent MCP operations, ensuring that static defaults and user additions coexist without collision.

Runtime Usage and Client Operations

RPC-exposed tools such as mcp_list_servers and mcp_call_tool, along with the internal HTTP client implemented in src/openhuman/mcp/http_client.rs, query the global registry to obtain concrete McpServer instances. Core server-side abstractions in src/openhuman/mcp/server.rs handle request validation and error mapping, while src/openhuman/mcp/audit.rs records request metadata for observability.

// ---------------------------------------------------------------------
// Example – Front‑end (React) fetching the list via RPC
// ---------------------------------------------------------------------
import { coreRpcClient } from "@/services/coreRpcClient";

async function fetchMcpServers() {
  const servers = await coreRpcClient.call("mcp_list_servers", {});
  return servers; // [{id, url, bearer?}, …]
}
// ---------------------------------------------------------------------
// Example – Listing all MCP servers (static + dynamic) from Rust
// ---------------------------------------------------------------------
use openhuman_core::mcp::registry::McpServerRegistry;

let registry = McpServerRegistry::global(); // reads the merged list
for server in registry.all() {
    println!(
        "ID: {}   URL: {}   Token: {}",
        server.id,
        server.url,
        server.bearer.as_deref().unwrap_or("<none>")
    );
}

Why OpenHuman Implements Dual Discovery Mechanisms

The coexistence of static and dynamic registration serves distinct operational requirements within the OpenHuman architecture.

Static configuration guarantees that essential MCP services remain reachable even before user workspaces exist, making it ideal for production deployments where server sets are immutable and system-critical defaults must persist across environments.

Dynamic registry provides the flexibility required for end-user customization, allowing orchestrators to add custom MCP endpoints without touching version-controlled configuration files. Because the registry lives in the user workspace (~/.openhuman), it inherits the same security and isolation guarantees as other user data, enabling safe multi-tenant scenarios.

Together, these mechanisms allow OpenHuman to seamlessly blend built-in MCP backends with user-defined ones, maintaining a clear separation between immutable defaults and mutable user state.

Summary

  • OpenHuman loads static MCP server definitions from [[mcp_client.servers]] blocks in config.toml via src/openhuman/mcp/config.rs, ensuring essential services are available before user workspaces load.
  • The dynamic registry in src/openhuman/mcp/registry.rs persists user-added servers to ~/.openhuman/mcp_clients.db and exposes CRUD operations through RPC calls like mcp_add_server.
  • During boot, src/openhuman/mcp/mod.rs calls load_static_servers() and load_registry_servers(), merges the results into a deduplicated global McpServerRegistry, and stores it in CoreContext.
  • The unified registry serves as the single source of truth for RPC tools and the HTTP client in src/openhuman/mcp/http_client.rs, which constructs requests using server-specific URL and authentication configuration.
  • This dual-path architecture separates immutable system defaults from user-driven customizations, enabling both reliable production deployments and flexible runtime extensibility.

Frequently Asked Questions

What is the difference between static and dynamic MCP server configuration in OpenHuman?

Static configuration resides in the immutable config.toml file and loads at boot time before user workspaces are available, ensuring critical services are always reachable. Dynamic configuration stores servers in a SQLite database within the user workspace (~/.openhuman), allowing runtime addition and modification through RPC calls without altering global configuration files.

How does OpenHuman handle duplicate MCP server entries from both configuration sources?

When the system boots, src/openhuman/mcp/mod.rs concatenates the static and dynamic server vectors and deduplicates them by server ID before storing them in the global McpServerRegistry. This ensures that entries with identical identifiers do not create conflicts in the unified catalog.

Can I modify static MCP server configurations at runtime in OpenHuman?

No, static configurations defined in the [[mcp_client.servers]] TOML block are immutable at runtime. To add or modify servers dynamically, use the registry RPC methods such as mcp_add_server, which persist changes to the SQLite-backed dynamic registry rather than the static configuration file.

Where does OpenHuman store dynamically added MCP server credentials?

Dynamically added servers are stored in the mcp_clients.db SQLite database located in the user's workspace directory at ~/.openhuman. This location ensures that server configurations follow the same security and isolation guarantees as other user-specific data, separate from the global system configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →