Integration Strategy for tinymcp with Over 5000 MCP Servers: A Three-Layer Architecture

OpenHuman delegates all Model Context Protocol (MCP) client implementation to the tinymcp crate using a thin façade pattern, enabling scalable management of thousands of servers through a registry-based supervisor that handles discovery, connection pooling, and transport abstraction.

The OpenHuman repository implements a sophisticated integration strategy to support massive-scale MCP server deployments. Rather than embedding MCP logic directly in the core, the architecture isolates complexity inside the tinymcp and tinymcp-bus crates, exposing only a minimal proxy interface to the main application. This design allows OpenHuman to manage catalogs containing over 5000 MCP servers while maintaining clean separation of concerns and supporting dynamic server discovery.

Three-Layer Architectural Pattern

The integration follows a strict three-layer pattern that isolates transport details from business logic. This structure ensures that adding new MCP servers requires only registry updates, never core code changes.

Layer 1: Facade — Located in src/openhuman/mcp/mod.rs, this layer re-exports public MCP APIs (McpHttpClient, McpStdioClient) and error types while documenting that the concrete implementation lives in tinymcp.

Layer 2: Registry & Supervisor — Implemented in src/openhuman/mcp/registry/mod.rs, this layer wraps the tinymcp registry and provides RPC-shaped entry points like all_connected_tools and connect_installed_servers.

Layer 3: Operations & Transport — Spread across src/openhuman/mcp/registry/ops.rs and src/openhuman/mcp/host.rs, this layer handles server-list curation and transport-specific client management.

Core Facade Implementation

The façade in src/openhuman/mcp/mod.rs (lines 3-15) serves as the sole entry point for MCP functionality in the OpenHuman core. It exposes the public API while hiding implementation details:

// The façade re-exports tinymcp types without exposing internal registry logic
pub use tinymcp::{McpHttpClient, McpStdioClient, McpError};
pub use tinymcp::registry::{connect_installed_servers, tools_for};

This design keeps the core independent of concrete MCP implementations. When the core needs to invoke an MCP tool, it calls through this façade, which delegates to the appropriate tinymcp client instance.

Registry and Supervisor Management

The registry layer in src/openhuman/mcp/registry/mod.rs (lines 279-315) manages the lifecycle of thousands of concurrent MCP connections. It instantiates tinymcp::Supervisor, which maintains a per-workspace store of server descriptors and a HashMap of live clients.

The registry implements sophisticated server selection logic:

// Official catalog servers are prioritized over user-added ones
let mut servers = load_official_catalog();
servers.extend(load_user_servers());
tag_official(&mut servers);  // Mark official entries
float_official_first(&mut servers);  // Reorder: official first

The connect_installed_servers function iterates over this merged list, establishing HTTP or stdio transports for each server. The supervisor stores active connections in supervisor.clients, enabling efficient lookup during tool invocation.

Transport Abstraction and Host Layer

The host layer in src/openhuman/mcp/host.rs (lines 1-24) holds a single tinymcp service instance per process. It converts generic proxy requests from the core into concrete transport calls:

// Host layer manages the singleton tinymcp service
pub struct McpHost {
    client: Arc<McpHttpClient>,  // Or McpStdioClient for local processes
}

impl McpHost {
    pub async fn proxy_for_mcp(&self, request: ProxyRequest) -> Result<ToolResult> {
        // Forward to tinymcp transport layer
        self.client.call_tool(request).await
    }
}

This abstraction supports both tinymcp::transport::http::McpHttpClient for remote servers and tinymcp::transport::stdio::McpStdioClient for local subprocesses, with the potential for future transports like TLS or Unix sockets.

Module-Based Delivery System

OpenHuman delivers the MCP client as a downloadable native module rather than compiling it into the main binary. The module registration in src/openhuman/modules/registry.rs (lines 662-742) declares tinymcp as the "MCP client" module:

ModuleManifest {
    name: "tinymcp",
    bus_name: "org.openhuman.mcp",
    object_path: "/org/openhuman/mcp",
    artifacts: vec![
        ("linux-x86_64", "https://.../tinymcp-linux-x86_64.tar.gz"),
        ("macos-arm64", "https://.../tinymcp-macos-arm64.tar.gz"),
        ("windows-x86_64", "https://.../tinymcp-windows-x86_64.tar.gz"),
    ],
}

This approach keeps the core binary size minimal for installations that do not require MCP functionality, while allowing dynamic loading of the client when needed.

Scaling to 5000+ MCP Servers

The architecture handles massive server catalogs through several scalability mechanisms:

Lazy Connection Pooling — The tinymcp::Supervisor maintains a descriptor store for all 5000+ servers but only establishes transport connections for servers actively being used, storing live clients in a HashMap keyed by server ID.

Catalog Merging Strategy — The registry loads the official catalog (containing thousands of pre-vetted servers) and merges user-installed entries, using tag_official and float_official_first to ensure reliable servers are tried first.

Per-Workspace Isolation — Each workspace maintains its own supervisor instance, preventing resource contention when multiple OpenHuman instances run simultaneously with different server subsets.

Practical Implementation Examples

Creating a supervisor and connecting installed servers:

use tinymcp::{Supervisor, SupervisorConfig};
use tinymcp_bus::McpClientIdentityConfig;

// Initialize supervisor with workspace-specific configuration
let mut supervisor = Supervisor::new(
    SupervisorConfig::default(),
    McpClientIdentityConfig::default(),
);

// Connect all servers from official catalog and user store
tinymcp::registry::connect_installed_servers(
    &mut supervisor,
    identity,
    proxy
)?;

Querying tools from a specific server:

// Access tools for a specific MCP server by ID
let server_id = "official-search-server";
let available_tools = tinymcp::registry::tools_for(server_id).await?;
println!("Server {} provides {} tools", server_id, available_tools.len());

Invoking tools through the OpenHuman RPC layer:

// High-level RPC call that routes through tinymcp internally
let result = core_rpc_client.call(
    "mcp_call_tool",
    json!({
        "server_id": "filesystem-mcp",
        "tool_id": "read_file",
        "args": { "path": "/tmp/data.txt" }
    })
).await?;

Summary

  • Separation of concerns — OpenHuman's core contains only a thin façade in src/openhuman/mcp/mod.rs; all MCP logic lives in the versioned tinymcp crate.
  • Scalable registry — The supervisor pattern in src/openhuman/mcp/registry/mod.rs supports thousands of servers through lazy connection management and efficient catalog merging.
  • Transport flexibility — HTTP and stdio transports are supported via McpHttpClient and McpStdioClient, with the host layer abstracting transport details.
  • Dynamic prioritization — Official catalog servers are automatically prioritized over user-added servers using float_official_first.
  • Modular deployment — The MCP client is delivered as a downloadable native module declared in src/openhuman/modules/registry.rs, reducing base binary size.

Frequently Asked Questions

How does OpenHuman handle over 5000 MCP servers without performance degradation?

OpenHuman uses lazy connection pooling through the tinymcp::Supervisor. While the registry maintains descriptors for all servers in src/openhuman/mcp/registry/mod.rs, transport connections are only established for actively used servers and stored in a HashMap. Official servers are prioritized via float_official_first, ensuring the most reliable endpoints are queried first when iterating through large catalogs.

What is the difference between official and user-added MCP servers?

Official servers come from the tinymcp release catalog and are marked via the tag_official function in src/openhuman/mcp/registry/ops.rs. These pre-vetted servers float to the top of the connection list. User-added servers are loaded from the local workspace store and appended after official ones. This distinction ensures stability when operating with thousands of potential servers.

Can I add custom MCP transports beyond HTTP and stdio?

Yes. The transport layer is abstracted through the host interface in src/openhuman/mcp/host.rs. While the current implementation exposes tinymcp::transport::http::McpHttpClient and tinymcp::transport::stdio::McpStdioClient, the façade pattern allows new transports (such as TLS or Unix sockets) to be added to tinymcp without modifying OpenHuman's core code.

How is the tinymcp module delivered to OpenHuman installations?

The module is declared in src/openhuman/modules/registry.rs (lines 662-742) as a downloadable native module with platform-specific artifact URLs for Linux, macOS, and Windows. OpenHuman downloads and loads this module at runtime, keeping the core binary lightweight for users who do not require MCP functionality while enabling full MCP client capabilities for those who do.

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 →