Multi-Server Tool Discovery¶
jpx provides BM25-based semantic search for discovering tools across multiple MCP servers. This enables natural language queries like "how do I backup a database?" instead of scanning flat tool lists.
The Problem¶
When an agent connects to multiple MCP servers, it has access to dozens or hundreds of tools. Finding the right tool for a task means:
- Scanning tool names hoping for a match
- Reading descriptions one by one
- Missing tools with different terminology ("backup" vs "snapshot" vs "export")
The Solution: Registration + Search¶
jpx provides a discovery registry that indexes tools from any MCP server using BM25 (the algorithm behind search engines). The workflow:
- Register: Agent registers each server's tools with jpx
- Search: Agent queries across all registered tools semantically
- Discover: BM25 finds relevant tools even with different wording
Architecture¶
MCP servers don't communicate with each other - they only respond to the agent. The agent orchestrates registration:
┌─────────┐ ┌─────────────┐ ┌─────────────┐
│ Agent │────▶│ jpx │ │ redisctl │
│ │────▶│ (registry) │ │ (65 tools) │
│ │────▶│ │ └─────────────┘
│ │ └─────────────┘ ┌─────────────┐
│ │────────────────────────▶│ other-mcp │
│ │ │ (N tools) │
└─────────┘ └─────────────┘
│
│ 1. Connect to all servers
│ 2. Get tool metadata from each
│ 3. Register with jpx
│ 4. Query jpx for tool discovery
▼
Discovery Tools¶
Registration¶
| Tool | Description |
|---|---|
register_tools |
Register an MCP server's tools for BM25 indexing |
unregister_discovery |
Remove a server from the registry |
Search¶
| Tool | Description |
|---|---|
query_tools |
BM25 semantic search across all registered tools |
similar_tools |
Find tools related to a specific tool |
Browse¶
| Tool | Description |
|---|---|
list_discovery_servers |
List all registered servers |
list_discovery_categories |
List tool categories across servers |
engine_info |
Get index statistics (via include_index_stats and include_schema parameters) |
Registration Schema¶
Register a server's tools with register_tools:
{
"spec": {
"server": {
"name": "redisctl",
"version": "0.1.0",
"description": "Redis management tools"
},
"tools": [
{
"name": "enterprise_database_create",
"description": "Create a new Redis Enterprise database with specified configuration",
"category": "enterprise",
"subcategory": "database",
"tags": ["database", "create", "write"],
"examples": ["Create a 500MB database named 'cache'"]
},
{
"name": "enterprise_database_backup",
"description": "Trigger a backup snapshot of a Redis Enterprise database",
"category": "enterprise",
"subcategory": "database",
"tags": ["database", "backup", "snapshot", "read"]
}
],
"categories": {
"enterprise": {
"description": "Redis Enterprise on-premises tools",
"tool_count": 30
}
}
},
"replace": false
}
Minimal Schema¶
Only server.name and tools[].name are required:
{
"spec": {
"server": { "name": "myserver" },
"tools": [
{ "name": "tool_one" },
{ "name": "tool_two" }
]
}
}
Full Schema¶
For best search results, include rich metadata:
description: Natural language description (indexed for search)category/subcategory: For browsing and filteringtags: Keywords that improve search relevanceexamples: Usage examples (indexed for search)inputSchema: Parameter documentation
Searching¶
Semantic Search¶
Returns ranked results with scores:
[
{
"tool_id": "redisctl:enterprise_database_backup",
"server": "redisctl",
"name": "enterprise_database_backup",
"description": "Trigger a backup snapshot of a Redis Enterprise database",
"score": 8.42,
"category": "enterprise"
},
{
"tool_id": "redisctl:enterprise_database_export",
"server": "redisctl",
"name": "enterprise_database_export",
"description": "Export database data to RDB file",
"score": 5.17,
"category": "enterprise"
}
]
Similar Tools¶
Find tools related to one you know:
Returns tools with similar descriptions/tags - useful for finding alternatives or related operations.
Agent Workflow¶
Manual Registration¶
At session start, register each server:
1. Get tool list from redisctl (agent already has this via MCP)
2. Call jpx.register_tools with redisctl's tools
3. Repeat for other MCP servers
4. Use query_tools for semantic search
Automatic Registration (Recommended)¶
Add to your agent's system prompt or CLAUDE.md:
## MCP Tool Discovery
At session start, if jpx and other MCP servers are available:
1. For each non-jpx MCP server, register its tools with jpx:
- Extract tool name, description, and input schema
- Call `mcp__jpx__register_tools` with the server name and tool list
2. When searching for tools, use `mcp__jpx__query_tools` for semantic search
instead of scanning the tool list manually.
3. Use `mcp__jpx__similar_tools` to find related tools when exploring options.
Example: Multi-Server Setup¶
With jpx + redisctl + github-mcp:
// Register redisctl (65 tools)
register_tools({
spec: {
server: { name: "redisctl", version: "0.1.0" },
tools: [
{ name: "enterprise_database_create", description: "...", category: "enterprise" },
{ name: "enterprise_database_backup", description: "...", category: "enterprise" },
// ... 63 more tools
]
}
})
// Register github-mcp (20 tools)
register_tools({
spec: {
server: { name: "github", version: "1.0.0" },
tools: [
{ name: "create_issue", description: "Create a GitHub issue", category: "issues" },
{ name: "list_pull_requests", description: "List PRs for a repo", category: "pulls" },
// ... 18 more tools
]
}
})
// Now search across both!
query_tools({ query: "create new resource", top_k: 10 })
// Returns: enterprise_database_create, create_issue, enterprise_crdb_create, ...
BM25 Scoring¶
The search uses BM25, a proven ranking algorithm that:
- Weights rare terms higher: "kubernetes" is more distinctive than "create"
- Handles term frequency saturation: Repeating a word doesn't linearly increase relevance
- Normalizes by document length: Short and long descriptions scored fairly
This means "backup database" finds tools mentioning "snapshot", "export", "persist" if those terms appear in similar contexts across the corpus.
Session Scope¶
The registry is session-scoped (in-memory):
- Fresh index each agent session
- No persistence across sessions
- Cheap to rebuild from source
This is intentional - tool metadata changes, and re-registration ensures the index matches current reality.
Inspecting the Index¶
Debug with engine_info (set include_index_stats: true):
{
"server_count": 2,
"tool_count": 85,
"term_count": 342,
"avg_doc_length": 12.4,
"servers": ["redisctl", "github"]
}
List categories with list_discovery_categories: