Skip to content

Context Management

Overview

The MCP protocol eagerly loads all tool signatures when a server connects. Each tool's name, description, and full JSON Schema consumes tokens in the AI's context window before the conversation even starts. With 49 core tools across five servers plus external integrations, this baseline cost reaches 10,000-20,000+ tokens — a significant fraction of the available context on smaller-window models and a cost multiplier on every request.

Crow addresses this with two complementary strategies: the Gateway Tool Router (HTTP deployments) and On-Demand Server Activation (stdio deployments). Both build on the same server factory pattern and InMemoryTransport plumbing.

Gateway Tool Router

The router (servers/gateway/router.js) consolidates all core and external tools behind 7 category tools, reducing context usage by approximately 75%.

Architecture

                        +-----------------------+
  [AI Client] -------->| /router/mcp           |
                        |  crow-router McpServer|
                        +-----------+-----------+
                                    |
            +-----------+-----------+-----------+-----------+
            |           |           |           |           |
     crow_memory  crow_projects  crow_blog  crow_sharing  crow_storage
            |           |           |           |           |
     [InMemory   [InMemory   [InMemory   [InMemory   [InMemory
      Transport]  Transport]  Transport]  Transport]  Transport]
            |           |           |           |           |
     [Memory     [Projects   [Blog       [Sharing   [Storage
      McpServer]  McpServer]  McpServer]  McpServer]  McpServer]

  crow_tools -----> connectedServers (from proxy.js)
  crow_discover --> static manifests + live schema lookup

Each category tool creates an in-process Client connected to the underlying McpServer via InMemoryTransport.createLinkedPair(). Clients are created lazily on first use within each session.

Router Tools

ToolDispatches ToActions
crow_memoryMemory server12 (store, search, recall, list, update, delete, stats, context ops)
crow_projectsProject server12 (projects, sources, notes, bibliography, stats)
crow_blogBlog server12 (create, edit, publish, list, delete, export, themes, stats)
crow_sharingSharing server8 (invite, contacts, share, inbox, messaging, revoke)
crow_storageStorage server5 (upload, list, download URL, delete, stats)
crow_toolsExternal proxy serversDynamic (Trello, Canvas, Slack, etc.)
crow_discoverStatic manifests + live schemasDiscovery protocol

Parameter Schema

Every category tool accepts the same shape:

js
{
  action: z.string(),    // Action name, e.g. "store_memory" or "crow_store_memory"
  params: z.record(z.any()).optional()  // Parameters forwarded to the underlying tool
}

The router resolves tool names with or without the crow_ prefix, so both store_memory and crow_store_memory work.

Compressed Manifests

Each category tool's description is built by buildCompressedDescription() from tool-manifests.js. It packs all action names and parameter signatures into the tool description string:

Persistent memory: store, search, recall, list... Actions:
- store_memory(content, category?, context?, tags?, source?, importance?): Store a memory
- search_memories(query, category?, min_importance?, limit?): Search memories (FTS5)
...

This gives the AI enough information to call most actions without discovery, while keeping the schema footprint small.

Discovery Protocol

The crow_discover tool provides on-demand access to full JSON Schemas:

crow_discover()                              → List all categories with action counts
crow_discover(category="memory")             → List memory actions with param summaries
crow_discover(category="memory", action="crow_store_memory") → Full JSON Schema
crow_discover(category="tools")              → List external integration tools
crow_discover(category="tools", action="github_create_issue") → Full external tool schema

Category-level discovery uses static manifests (no server instantiation). Action-level discovery calls client.listTools() on the underlying server to return the live schema.

Context Savings

ModeTools LoadedEstimated Tokens
Individual servers (no router)49 x ~200 tokens~9,800
Router mode7 x ~350 tokens~2,450
Reduction~75%

Feature Flag

Disable the router to mount servers individually:

bash
CROW_DISABLE_ROUTER=1 npm run gateway

On-Demand Server Activation (crow-core)

For stdio deployments, servers/core/ provides a single MCP server that starts with one server active and adds others on demand.

Architecture

  [AI Client] <--stdio--> [crow-core McpServer]
                                |
                          +-----+-----+
                          |           |
                   [Active Tools]  [Management Tools (3)]
                   (memory: 12)    crow_activate_server
                                   crow_deactivate_server
                                   crow_server_status

  crow_activate_server("projects")
        |
        v
  [registeredTool.enable()] --> toolListChanged notification
        |
        v
  [AI re-fetches tool list] --> project tools now visible

Management Tools

ToolParametersDescription
crow_activate_serverserver: stringEnable a server's tools (memory, projects, sharing, storage, blog)
crow_deactivate_serverserver: stringDisable a server's tools (default server cannot be deactivated)
crow_server_statusnoneShow active/inactive servers with tool counts

Startup Behavior

  1. All servers are connected via InMemoryTransport and their tools registered on the core McpServer
  2. Only the default server's tools are enabled; all others are registered but disabled
  3. The AI sees 15 tools at startup: 12 memory tools + 3 management tools
  4. Calling crow_activate_server("projects") flips the registered tools to enabled and triggers a toolListChanged notification
  5. The AI client re-fetches the tool list and sees the newly available tools

The default server is configurable:

bash
CROW_DEFAULT_SERVER=projects node servers/core/index.js

Automatic Behavioral Context (MCP Instructions)

The MCP protocol supports an instructions field in the InitializeResult — a string sent during the connection handshake before any tool calls. Per the spec, this "can be used by clients to improve the LLM's understanding of available tools" and "MAY be added to the system prompt."

Crow uses this to deliver behavioral context automatically to every connected AI client, eliminating the need for users to manually ask the AI to load crow.md.

How It Works

  Gateway startup
       |
       v
  generateInstructions() ──> queries crow_context table
       |                     extracts 5 essential sections
       v                     condenses to ~1KB string
  instructions string (pre-computed)
       |
       +──> createMemoryServer(undefined, { instructions })
       +──> createProjectServer(undefined, { instructions })
       +──> createRouterServer({ instructions: routerInstructions })
       +──> ...
       |
       v
  McpServer({ name, version }, { instructions })
       |
       v
  Client connects ──> InitializeResult includes instructions
       |
       v
  AI sees behavioral context before any tool calls

The instructions string is generated once at gateway startup and passed to all server factories as a pre-computed string. This avoids per-session database queries and keeps factories synchronous.

Content

The condensed instructions (~1KB) include:

SectionContent
IdentityWho Crow is (1-2 sentences)
Session Protocol"Call crow_recall_by_context on session start"
Memory ProtocolCategories, importance levels, deduplication rules
Transparency Rules[crow: action] notation for autonomous actions
CapabilitiesTool routing table (direct names or category names for router)

Two variants are generated:

  • Direct style: Uses tool names like crow_store_memory (for individual server endpoints)
  • Router style: Uses category names like crow_memory action: "store_memory" (for /router/mcp)

Fallback

If the crow_context table doesn't exist or the database is unavailable, a static ~500-byte fallback is used that provides minimal behavioral guidance.

Per-Device Overrides

All context generation functions (generateCrowContext, generateCondensedContext, generateInstructions) accept an optional deviceId parameter. When provided, the system queries all crow_context rows and merges global sections (device_id IS NULL) with device-specific sections (device_id = ?). Device-specific sections override globals with the same section_key; device-only sections are appended.

The crow_context table uses two partial unique indexes to enforce uniqueness: one for global sections (WHERE device_id IS NULL) and one for device-specific sections (WHERE device_id IS NOT NULL).

stdio Servers

stdio entry points (servers/*/index.js) generate instructions at startup using top-level await, then pass the string to the factory. crow-core does the same inside its async createCoreServer() function.

MCP Prompts (Skill Equivalents)

MCP prompts are first-class prompt templates that clients can list and request on demand. Crow registers prompts as skill equivalents for non-Claude-Code platforms, giving the AI access to detailed workflow guidance without consuming context window space upfront.

Available Prompts

PromptServer(s)Description
session-startMemory, RouterSession start/end protocol from crow.md
crow-guideMemory, RouterFull crow.md document (accepts platform argument)
research-guideProjects, RouterResearch workflow: projects, sources, citations, bibliography
blog-guideBlog, RouterBlog publishing: posts, themes, RSS, export
sharing-guideSharing, RouterP2P sharing: invites, contacts, messaging

The router registers all 5 prompts so clients connected to /router/mcp have access to everything. Individual servers register only their own relevant prompts.

How Clients Use Prompts

Client: prompts/list
Server: [{ name: "session-start", description: "..." }, ...]

Client: prompts/get { name: "crow-guide", arguments: { platform: "chatgpt" } }
Server: { messages: [{ role: "user", content: { type: "text", text: "# crow.md — ..." } }] }

The AI can request a prompt when it needs detailed guidance for a specific workflow, keeping the initial context footprint small while making comprehensive instructions available on demand.

Server Factory Integration

Both the router and crow-core reuse the same factory functions (createMemoryServer, createProjectServer, etc.) and the same InMemoryTransport + Client pattern. The factory creates a standalone McpServer; the caller wires it to whatever transport the deployment needs:

js
// stdio (individual server)
const server = createMemoryServer();
await server.connect(new StdioServerTransport());

// Gateway router (in-process)
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
await client.connect(clientTransport);

// crow-core (same in-process pattern, tools proxied onto core McpServer)

Static tool metadata lives in servers/gateway/tool-manifests.js. Both the router (buildCompressedDescription) and crow-core (getToolNames) import from it.

Configuration

.mcp.json Generation

bash
# Individual servers (one entry per server in .mcp.json)
npm run mcp-config

# Combined crow-core mode (single entry)
npm run mcp-config -- --combined

The --combined flag writes a single crow-core entry pointing to servers/core/index.js instead of separate entries for each server. The server registry in scripts/server-registry.js defines both modes.

Health Endpoint

The gateway /health response includes tool count telemetry:

json
{
  "status": "ok",
  "servers": ["crow-memory", "crow-projects", "crow-sharing", "crow-storage", "crow-blog"],
  "externalServers": [{ "id": "github", "name": "GitHub", "tools": 15 }],
  "toolCounts": {
    "core": 49,
    "external": 15,
    "total": 64,
    "routerMode": 7
  }
}

The routerMode field is the number of router tools exposed (7), or null when the router is disabled via CROW_DISABLE_ROUTER=1.

API Reference

EndpointMethodDescription
/router/mcpPOST, GET, DELETEStreamable HTTP transport for the router McpServer
/healthGETStatus including toolCounts object

For usage guidance and optimization tips, see the Context Performance Guide.

Released under the MIT License.