The Problem It Solves
Traditional application integrations are point-to-point. If you want your CRM to access data from your ERP, you build an integration between them. Add a ticketing system? Build two more integrations. The work scales quadratically—N applications require up to N² integrations. AI agents promised to change this. Instead of rigid integrations, the agent would understand both systems and coordinate between them. But for this to work, the agent needs visibility into all the applications simultaneously. The naive solution—putting all tool definitions into a single system prompt—doesn’t scale. Tools from five applications might fit. Tools from fifty won’t. And it doesn’t solve the execution problem: how does an agent invoke a tool that executes in a different context than where the agent runs? The Tool Hub solves both problems. It’s a registry that tools register with dynamically, and a router that forwards invocations to wherever the tool actually executes—whether that’s a browser tab, an internal service, or an external API.What Gets Aggregated
The Hub aggregates tools from three distinct sources, each with different execution models: Browser-based tools (WebMCP) register when a page with Char embedded loads. The page announces its available tools over a WebSocket connection. When invoked, the Hub routes the request back to that specific browser tab, where execution happens using the user’s session. Internal remote MCP servers register through connector configuration. These are services your enterprise operates—data platforms, internal APIs, custom tooling. They connect to the Hub over HTTP, and invocations route directly to them. Authentication uses the same identity that’s already established for the user. External MCP servers also register through connector configuration, but with a different trust model. These are third-party services the user has authorized. The Hub manages OAuth tokens and routes invocations to the external service. From the agent’s perspective, these distinctions are invisible. It sees a unified list of tools and invokes them the same way. The Hub handles the routing complexity.Why Per-User Scoping
A simpler architecture would have a single Tool Hub per organization. All users share the same registry, tools are available to everyone. This creates problems: Permission confusion. Users have different permissions in different applications. Alice might have admin access to the CRM but read-only access to the ERP. A shared registry can’t model this—either everyone sees all tools (security risk) or tools need complex permission logic (complexity explosion). Session isolation. Browser-based tools execute using browser sessions. Alice’s CRM session is different from Bob’s CRM session. If they shared a registry, whose session would the tool use? Connector scoping. Remote MCP connections carry user identity. A shared Hub would need to multiplex connections per-user anyway, defeating the simplification. Privacy. Users might not want colleagues seeing what applications they have open, what external services they’ve connected, or what tools they’re using. Per-user scoping sidesteps all of this. Alice has her own Hub with her tools, using her sessions and her connections. Bob has his own Hub. There’s no complexity from trying to model multi-user access because there’s no multi-user access to model. The cost is that users can’t directly share tools or collaborate through the Hub. In practice, this isn’t a limitation—users collaborate through the applications themselves, not through the agent infrastructure.Why Cloudflare Durable Objects
The Tool Hub is implemented as a Cloudflare Durable Object. This choice deserves explanation because it has significant implications. Durable Objects provide strongly consistent, single-threaded state at the edge. Each Hub instance is a JavaScript object with its own storage, guaranteed to run in a single location at any given time. This means: No coordination overhead. When multiple browser tabs and remote services connect to the same Hub, they connect to the same physical instance. There’s no distributed consensus, no eventual consistency, no race conditions between replicas. The Hub’s state is always coherent. Geographic affinity. Durable Objects run close to where they’re accessed. If Alice is in London, her Hub runs in a European datacenter. WebSocket connections from her browser tabs and HTTP connections from internal services have low latency. Automatic scaling. Each user’s Hub is a separate instance. A million users means a million independent Hubs, each handling its own load. There’s no shared infrastructure to become a bottleneck. Infrastructure-level isolation. Cross-user access isn’t just prohibited by application logic—it’s structurally impossible. There’s no code path that could retrieve another user’s Hub because each Hub is a distinct entity in Cloudflare’s infrastructure.Alternatives Considered
Redis or traditional databases. These require careful sharding to avoid hotspots, complex coordination for WebSocket routing, and explicit isolation logic. They work, but they trade operational simplicity for flexibility we don’t need. In-memory state with sticky sessions. This loses durability—if the server restarts, state is lost. It also complicates deployment across multiple regions. Actor frameworks (Akka, Orleans). These could work but require managing infrastructure. Durable Objects provide the actor model as a managed service. The Durable Objects choice reflects a broader principle: use infrastructure-level guarantees where possible rather than application-level complexity.How Tool Registration Works
Tools register differently depending on their source.Browser-Based Tools
When a browser tab with Char embedded loads, it establishes a WebSocket connection to the user’s Tool Hub. Through this connection, the page registers its available tools: When the browser tab closes, its WebSocket disconnects, and the Hub removes those tools from the registry. The Hub reflects reality—you can only invoke tools from applications that are actually open.Remote MCP Servers
Internal and external MCP servers register through connector configuration at the organization level. The Hub discovers their tools by calling the standard MCPtools/list endpoint:
The Hub caches tool schemas but refreshes them periodically and on-demand. If a remote server adds or removes tools, the Hub discovers this on the next sync.

