> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usechar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Tool Hub

> Why Char uses a per-user aggregation layer and how it enables cross-application workflows

The Tool Hub is the central orchestration layer of Char—a per-user registry that aggregates tools from browser tabs, internal services, and external applications. Understanding why it exists and how it's built explains much of what makes Char's architecture distinctive.

## 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.

```mermaid theme={null}
graph LR
    subgraph Point-to-Point
        A1[App A] <--> B1[App B]
        A1 <--> C1[App C]
        B1 <--> C1
        A1 <--> D1[App D]
        B1 <--> D1
        C1 <--> D1
    end
```

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.

```mermaid theme={null}
graph TD
    subgraph Sources["Tool Sources"]
        Browser[Browser Tabs<br/>WebMCP Tools]
        Internal[Internal Services<br/>Remote MCP]
        External[External Services<br/>OAuth-Connected]
    end

    Hub[Tool Hub<br/>Per-User Registry]

    Browser <-->|WebSocket| Hub
    Internal <-->|HTTP| Hub
    External <-->|HTTP + OAuth| Hub

    Agent[AI Agent] <-->|Unified Interface| Hub
```

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.

```mermaid theme={null}
graph TD
    subgraph Alice["Alice's Context"]
        A1[Browser Tab 1]
        A2[Browser Tab 2]
        A3[Internal MCP]
    end

    subgraph Bob["Bob's Context"]
        B1[Browser Tab 1]
        B2[Internal MCP]
    end

    AH[Alice's Durable Object<br/>London datacenter]
    BH[Bob's Durable Object<br/>NYC datacenter]

    A1 <-->|WebSocket| AH
    A2 <-->|WebSocket| AH
    A3 <-->|HTTP| AH
    B1 <-->|WebSocket| BH
    B2 <-->|HTTP| BH
```

### 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:

```mermaid theme={null}
sequenceDiagram
    participant Page as Browser Page
    participant Hub as Tool Hub

    Page->>Hub: Connect (WebSocket)
    Hub-->>Page: Connected
    Page->>Hub: Register tools [search, updateRecord, ...]
    Hub->>Hub: Add to registry with tab namespace
    Hub-->>Page: Registered

    Note over Hub: Registry now contains<br/>crm_search, crm_updateRecord, ...
```

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 MCP `tools/list` endpoint:

```mermaid theme={null}
sequenceDiagram
    participant Hub as Tool Hub
    participant MCP as Remote MCP Server

    Hub->>MCP: tools/list (with user identity)
    MCP-->>Hub: Available tools [queryData, createTicket, ...]
    Hub->>Hub: Add to registry with connector namespace

    Note over Hub: Registry now contains<br/>dataplatform_queryData, ticketing_createTicket, ...
```

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.

## Tool Invocation Routing

When a tool is invoked, the Hub routes the request to the correct destination:

```mermaid theme={null}
sequenceDiagram
    participant Agent as AI Agent
    participant Hub as Tool Hub
    participant Tab as Browser Tab
    participant MCP as Remote MCP

    Agent->>Hub: Call crm_updateRecord({...})
    Hub->>Hub: Lookup tool source
    alt Browser-based tool
        Hub->>Tab: Forward request (WebSocket)
        Tab->>Tab: Execute with user session
        Tab-->>Hub: Result
    else Remote MCP tool
        Hub->>MCP: tools/call (HTTP)
        MCP-->>Hub: Result
    end
    Hub-->>Agent: Return result
```

For browser-based tools, the Hub never sees the actual API calls or data—it only routes messages. Execution happens entirely in the browser tab.

For remote MCP tools, the Hub acts as an authenticated proxy. It attaches appropriate credentials and forwards the request. The remote server sees a request from the authenticated user, not from a generic service account.

## What the Hub Enables

This architecture enables capabilities that would otherwise require significant integration work:

**Cross-source workflows.** An agent can invoke browser-based CRM tools, internal data platform queries, and external calendar operations in a single workflow. The Hub unifies them under one interface.

**External client access.** Claude Desktop or VS Code can invoke all tools via the MCP protocol—browser-based tools, internal services, external applications. The Hub bridges desktop applications and the full tool ecosystem.

**Centralized policy.** Because all tool invocations flow through the Hub, policy enforcement happens in one place. Classification, approval workflows, and audit logging don't need to be implemented in each application or service.

**Graceful degradation.** If a browser tab closes, its tools become unavailable. If a remote service goes down, those tools stop working. The Hub tracks what's actually available, not what might theoretically be available.

**Identity continuity.** Every tool invocation carries the same user identity. Browser tools use the user's session. Remote tools use tokens derived from the user's IDP token. The audit trail is consistent across all sources.

## The Tradeoffs

The Hub architecture involves real tradeoffs:

**Browser dependency for WebMCP.** Browser-based tools require browser tabs. No tabs, no tools. This is intentional—browser-based execution enables session inheritance—but it means WebMCP isn't suitable for background automation in its basic form. For unattended workflows, enterprise deployments can use remote browsers with delegated credentials.

**Latency.** Cross-application tool calls involve multiple hops. Browser tools: agent → Hub → browser tab → application API → browser tab → Hub → agent. Remote tools: agent → Hub → remote server → Hub → agent. For interactive use cases, the latency is acceptable. For high-frequency automation, it might not be.

**Complexity for simple cases.** If you only have one application and don't need cross-app workflows, the Hub adds architectural complexity without benefit. Char's Tier 0 (page-scoped) mode exists for these cases.

**Connector management.** Remote MCP connections require configuration—server URLs, authentication settings, trust classification. This is operational overhead that browser-based tools don't have.

## Further Reading

<CardGroup cols={2}>
  <Card title="Why Char Exists" icon="lightbulb" href="/explanation/how-char-works">
    The problem Char solves and the three tool sources
  </Card>

  <Card title="Organizational Learning" icon="brain" href="/explanation/organizational-learning">
    How Hub-mediated execution enables context capture
  </Card>

  <Card title="Session Inheritance" icon="key" href="/explanation/session-inheritance">
    Why browser-based tools work the way they do
  </Card>

  <Card title="Deployment Tiers" icon="layer-group" href="/explanation/deployment-tiers">
    When you need the Hub vs simpler modes
  </Card>
</CardGroup>
