How MCP Transports Align With Core Socket Behavior in OpenHuman

MCP transports in OpenHuman reuse the core socket layer's HTTP client, WebSocket channels, TLS configuration, and authentication store, ensuring identical network behavior and security policies across native RPC and external service calls.

The OpenHuman framework implements a unified communication architecture where Multiplexed Channel Protocol (MCP) transports directly leverage the core socket infrastructure instead of maintaining a separate network stack. This design, implemented in the tinyhumansai/openhuman repository, guarantees consistent request signing, error classification, and observability across both internal RPC endpoints and external service integrations.

Core Socket Architecture

The foundation resides in src/core/socket.rs, which exposes a JSON-RPC endpoint over a local HTTP server and an optional WebSocket (Socket.IO) channel for push events. This layer handles live agent updates, thread notifications, and audit logs through a single, centralized network stack that powers both the desktop UI via Tauri and headless embeds.

MCP Transport Integration Points

The MCP package located in src/openhuman/mcp/ provides a generic transport abstraction for external services including cloud-hosted AI backends and third-party channel providers. Rather than implementing isolated networking logic, MCP reuses the core socket primitives through six critical alignment strategies.

Shared HTTP Client and Request Signing

McpHttpClient performs all MCP calls over the same HTTP client that the core uses for its own RPC traffic. Located in src/openhuman/mcp/client/http.rs, this client automatically injects the x-sdk-name header and authentication credentials that the core expects, ensuring identical request signing and timeout handling across both layers.

MCP clients pull the current bearer token from the global CoreContext using the core-wide BearerToken store. This integration means that token rotations performed by the core during session refreshes are instantly visible to MCP callers without additional configuration or re-authentication steps.

WebSocket Namespace Sharing

When the core socket enables WebSocket listeners, McpWebSocketTransport registers its own namespaces (/mcp/*) on the same channel. This implementation in src/openhuman/mcp/client/websocket.rs allows MCP-based tools to receive real-time events—including tool progress updates, server status notifications, and completion signals—without opening separate socket connections or consuming additional ports.

Unified TLS and Proxy Policies

Both layers share the transport::http_client module located in src/openhuman/mcp/http_client.rs. MCP inherits the core's TLS strategy—using Rustls on non-Windows platforms and Schannel on Windows—along with proxy resolution from config::proxy. This guarantees that MCP traffic respects the same corporate proxy policies as core RPC traffic, eliminating network configuration drift between internal and external service calls.

Common Error Classification Layer

MCP request errors funnel through rest::classify_sdk_error, the same error-mapping layer used by the core's SDK wrapper. This yields uniform error codes—such as Unauthorized for authentication failures, Transient for retryable network issues, and NotFound for missing resources—across both native RPC and MCP external service calls.

Consolidated Observability Pipeline

All MCP requests emit tracing spans through observability::tracing hooks, using identical span identifiers ([rpc], [mcp]) to native core RPC calls. This allows a single observability pipeline to capture latency metrics, retry attempts, and success rates across the entire stack without separate instrumentation configurations.

Practical Implementation Examples

Because MCP adopts the core socket's configuration, no additional network ports or credentials are required when enabling MCP tooling. The following examples demonstrate how to initialize MCP clients that automatically inherit core socket behavior.

Initializing an MCP HTTP Client

use openhuman::mcp::client::McpHttpClient;
use openhuman::core::builder::HarnessBuilder;

// Build a core harness with socket listener for live updates
let harness = HarnessBuilder::new()
    .provider(openhuman::provider::openai_compatible(
        "https://api.openai.com/v1",
        "sk-....",
    ))
    .access(openhuman::access::full())
    .socket(openhuman::socket::SocketConfig::enabled())
    .build()
    .await?;

// MCP client automatically re-uses the same HTTP client & bearer token
let mcp = McpHttpClient::new(&harness);
let servers = mcp.list_servers().await?;
println!("MCP servers: {:?}", servers);

Subscribing to MCP WebSocket Events

use openhuman::mcp::client::McpWebSocketTransport;
use futures_util::StreamExt;

let ws = McpWebSocketTransport::connect(&harness).await?;
let mut events = ws.subscribe("mcp.events");

// Process real-time MCP events (progress, completion, errors)
while let Some(event) = events.next().await {
    println!("MCP event: {:?}", event);
}

Streaming Tool Execution via Core Socket

let tool = mcp.tool("my_custom_tool");
let mut stream = tool.run_streaming(vec!["arg1", "arg2"]).await?;

// Process streamed chunks as they arrive through the core socket
while let Some(chunk) = stream.next().await {
    println!("Chunk: {}", String::from_utf8_lossy(&chunk));
}

Summary

  • HTTP client reuse: McpHttpClient in src/openhuman/mcp/client/http.rs automatically inherits the core's HTTP configuration, authentication headers, and timeout settings.
  • WebSocket channel sharing: McpWebSocketTransport registers on the core socket's existing WebSocket listener, enabling real-time events without additional connections.
  • Unified security posture: The shared transport::http_client module ensures both layers use identical TLS certificates and proxy resolutions from config::proxy.
  • Consistent error handling: MCP leverages rest::classify_sdk_error to produce uniform error codes across native RPC and external service calls.
  • Simplified testing architecture: Unit and integration tests can spin up a single in-process core instance using Harness::builder() to exercise both core RPC and MCP calls against the same mock server.

Frequently Asked Questions

How does MCP authentication align with core socket sessions?

MCP clients automatically pull the current bearer token from the global CoreContext store using the core-wide BearerToken implementation. When the core performs token rotation during session refreshes, MCP callers immediately receive the updated credentials without manual intervention, ensuring continuous authorization across both transport layers.

Can MCP operate without the core socket WebSocket enabled?

While MCP can function over HTTP without WebSocket support, disabling the core socket limits real-time event capabilities. The McpWebSocketTransport requires the core socket's WebSocket listener to be active in order to register its /mcp/* namespaces and receive push notifications for tool progress and server status updates.

What error codes does MCP share with the core socket layer?

MCP requests funnel through rest::classify_sdk_error, producing uniform error classifications including Unauthorized for authentication failures, Transient for retryable network issues, and NotFound for missing resources. This ensures consistent error handling logic across native RPC and MCP external service calls.

How does MCP handle corporate proxy configurations?

MCP inherits the core's proxy resolution from config::proxy through the shared transport::http_client module. This guarantees that all MCP traffic respects the same corporate proxy policies as core RPC traffic, using Rustls on non-Windows platforms and Schannel on Windows for TLS handling.

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 →