Problem Solved: Traditional MCP implementations expose all tools directly, consuming 40-80% of the context window before any actual work begins. The hierarchical router reduces this to <1% while maintaining full functionality.
Alternative Access Method: For direct MCP client integration without OAuth complexity, see Instance Router which provides token-based access to individual instances.
The Context Window Problem
Traditional MCP Architecture
When MCP clients connect to servers with many tools, the context window gets consumed by tool definitions:- Claude Code: 82,000 tokens consumed by MCP tools (41% of context)
- Industry consensus: 20-40 tools before performance degrades
- Cursor hard limit: 40 tools maximum
- Critical failures: 80+ tools cause suboptimal responses
Root Cause
MCP clients calltools/list to discover available tools, and servers respond with complete tool definitions including:
- Tool name
- Description (often 100+ characters)
- Input schema (JSON Schema objects)
- Parameter descriptions
- Examples and constraints
The Hierarchical Router Solution
Architecture Overview
Instead of exposing all tools directly, the satellite exposes only 4 meta-tools:Token Reduction
Before (Traditional):- 150 tools × 500 tokens = 75,000 tokens
- 37.5% of 200k context consumed
- 4 meta-tools × ~500 tokens = ~2000 tokens consumed
- Result: ~1.0% of context window used
- Token Reduction: 97.3%
Meta-Tool Specifications
Tool 1: discover_mcp_tools
Purpose: Search for available tools across all connected MCP servers using natural language queries. Definition:- Uses Fuse.js for fuzzy full-text search
- Searches across tool names, descriptions, and server names
- Returns results ranked by relevance score
- Search time: 2-5ms for 100+ tools
- Queries UnifiedToolDiscoveryManager for tool cache
Tool 2: execute_mcp_tool
Purpose: Execute a discovered tool by its path returned fromdiscover_mcp_tools.
Definition:
- Parses
tool_pathfrom external format (server:tool) to internal format (server-tool) - Looks up tool in unified cache to determine transport type
- Routes to appropriate handler (stdio or HTTP/SSE)
- Returns result in MCP content format
Tool 3: list_mcp_resources
Purpose: List all available resources across all connected MCP servers. Definition:- Returns all resources from connected MCP servers with namespaced URIs
- Resource metadata is cached during tool discovery (no extra round-trip)
_metafields are preserved for MCP Apps support_meta.ui.resourceUriis rewritten to use the namespaced URI format- Per-user filtering: only shows resources from the authenticated user’s installations
Tool 4: read_mcp_resource
Purpose: Read the content of a specific resource by its namespaced URI. Definition:- Parses the namespaced URI (
serverSlug|originalUri) to identify origin server - Content is never cached — always proxied on-demand to the origin MCP server
- Routes to the correct transport (stdio subprocess or HTTP/SSE endpoint)
- Per-user routing: resolves the authenticated user’s specific installation
- Supports both text and binary (base64) resource content
Complete User Flow
Step 1: Client Connects
Step 2: Client Discovers Available Tools
Step 3: User Asks for GitHub Tools
The AI agent (Claude) decides it needs GitHub tools:Step 4: User Executes Discovered Tool
The AI agent decides to usegithub:create_issue:
Step 5: User Lists Resources
The AI agent discovers available resources:Step 6: User Reads a Resource
The AI agent reads a specific resource:Format Conversion
The satellite converts between user-facing format (serverName:toolName) and internal routing format (serverName-toolName) transparently during tool discovery and execution.
See Tool Discovery - Namespacing Strategy for complete details on naming conventions and format conversion logic.
Search Implementation
Fuse.js Configuration
Search Performance
- Index Build: On-demand per search (no stale cache)
- Search Time: 2-5ms for 100+ tools
- Memory: Zero duplication (queries UnifiedToolDiscoveryManager directly)
- Accuracy: Handles typos, partial matches, fuzzy matching
Single Source of Truth
ToolSearchService queries UnifiedToolDiscoveryManager.getAllTools() directly for every search:- Always up-to-date (no cache invalidation needed)
- No memory duplication
- Automatic reflection of tool changes
Why Tool and Resource Notifications Are Irrelevant
The Question
“Should we implementnotifications/tools/list_changedornotifications/resources/list_changedwhen tools or resources are added or removed?”
The Answer
NO. The MCP client only sees 4 static meta-tools that NEVER change:discover_mcp_tools✅ Always availableexecute_mcp_tool✅ Always availablelist_mcp_resources✅ Always availableread_mcp_resource✅ Always available
- New MCP servers installed → Search index and resource cache update automatically
- MCP servers removed → Search index and resource cache update automatically
- Tools/resources discovered from new servers → Caches update automatically
- ✅ Backend sends configuration update to satellite
- ✅ Satellite spawns new MCP server process (if stdio)
- ✅ Tool and resource discovery runs automatically
- ✅ Search index and resource cache refreshed
- ❌ Client is NOT notified (doesn’t need to be)
discover_mcp_tools or list_mcp_resources, the new tools and resources are automatically included. No notification needed.
Performance Characteristics
Token Consumption
| Metric | Traditional | Hierarchical | Reduction |
|---|---|---|---|
| Tools Exposed | 150 | 4 | 97.3% |
| Tokens Consumed | 75,000 | ~2000 | 97.3% |
| Context Available | 62.5% | 99.0% | +36.5% |
Search Performance
- Discovery Latency: 2-5ms (including Fuse.js index build)
- Execution Latency: <1ms (routing overhead only)
- Memory Overhead: ~1KB per cached tool
- Scalability: No degradation up to 500+ tools
Real-World Impact
Claude Code Example:- Before: 82,000 tokens (41%) consumed by MCP tools
- After: ~2000 tokens (~1.0%) consumed by 4 meta-tools
- Result: ~80,000 tokens freed for actual work
Implementation Status
Status: ✅ Fully OperationalAll 4 meta-tools are implemented and production-ready:
discover_mcp_tools: Full-text search with Fuse.jsexecute_mcp_tool: Complete routing for stdio and HTTP/SSE transportslist_mcp_resources: Resource listing with per-user filtering and_metapreservationread_mcp_resource: On-demand resource proxying to origin servers
Code Locations
Core Implementation:/services/satellite/src/core/mcp-server-wrapper.ts- Meta-tool handlers/services/satellite/src/services/tool-search-service.ts- Search implementation/services/satellite/src/services/unified-tool-discovery-manager.ts- Tool cache/services/satellite/src/services/unified-resource-discovery-manager.ts- Resource cache/services/satellite/src/lib/mcp-resource-executor.ts- Resource read proxying
setupMcpServer()- Registers 4 meta-tools instead of all toolshandleDiscoverTools()- Implements tool discovery logichandleExecuteTool()- Implements tool execution routinghandleListResources()- Implements resource listing with per-user filteringhandleReadResource()- Implements on-demand resource proxying
Resource Support & _meta Preservation
Resource Discovery
Resources are discovered alongside tools during the same connection — no extra round-trip per server. When the satellite connects to an MCP server (stdio or HTTP/SSE), it calls bothtools/list and resources/list in sequence. Resource metadata (URI, name, description, mimeType) is cached, but resource content is never cached — it’s always proxied on-demand via McpResourceExecutor.
URI Namespacing
Resources use a pipe separator (|) for URI namespacing, different from the colon (:) used for tools:
ui://, file://, https://), which would conflict with the tool namespacing format.
_meta Preservation
The_meta field is preserved through the entire cache and response chain. This is important for MCP Apps support, where _meta carries UI rendering hints (e.g., _meta.ui.resourceUri tells the client which resource to load for an app-like experience).
Preservation chain:
- Origin MCP server returns
_metaon tools and resources - Discovery managers preserve
_metawhen caching (...(item._meta ? { _meta: item._meta } : {})) discover_mcp_toolsincludes_metain tool search resultslist_mcp_resourcesincludes_metain resource listings_meta.ui.resourceUriis rewritten to use the namespaced URI format so clients can read the resource through the hierarchical router
Resource vs Tool Flow
| Aspect | Tools | Resources |
|---|---|---|
| Discovery meta-tool | discover_mcp_tools | list_mcp_resources |
| Execution meta-tool | execute_mcp_tool | read_mcp_resource |
| URI separator | : (colon) | | (pipe) |
| Content caching | N/A (executed on-demand) | Never cached (proxied on-demand) |
| Metadata caching | Yes (tool definitions) | Yes (URI, name, mimeType) |
_meta support | Yes | Yes |
Benefits Summary
For Users:- 95%+ more context available for actual work
- Natural language tool discovery
- No performance degradation with many tools
- Transparent - works like any MCP server
- Simple 4-tool interface
- Automatic tool discovery
- No client modifications needed
- Standard MCP protocol compliance
- Scales to hundreds of tools
- No memory explosion
- Fast search performance
- Easy to monitor and debug
Status-Based Tool Filtering
The hierarchical router integrates with status tracking to hide tools from the user’s unavailable instances and provide clear error messages when unavailable tools are executed.Per-User Filtering: Each user sees only tools from their OWN instances that are online. Other team members’ instance status doesn’t affect your tool availability.
Related Documentation
- Tool Discovery Implementation - Internal tool caching and discovery
- Status Tracking - Tool filtering by per-user instance status
- Instance Lifecycle - Per-user instance management
- Recovery System - How offline servers auto-recover
- MCP Transport Protocols - How clients connect
- Process Management - stdio server lifecycle
- Architecture Overview - Complete satellite design

