How OmniRoute's MCP Server Exposes 109 Tools Across 33 Scopes
OmniRoute's Model Context Protocol (MCP) server exposes 109 tools grouped into 33 fine-grained scopes, with runtime scope enforcement through resolveCallerScopeContext and evaluateToolScopes functions that validate caller permissions before tool execution.
The OmniRoute project provides a sophisticated bridge between AI agents and enterprise routing capabilities through its MCP server implementation. This server allows Claude Desktop, Cursor, VS Code, and custom agents to invoke a rich catalog of tools while maintaining strict security boundaries. The scope-based architecture ensures multi-tenant deployments can control exactly what each agent is permitted to do.
Understanding the 109 Tools and 33 Scopes Architecture
OmniRoute's MCP server organizes its functionality into 109 distinct tools spanning core routing, memory management, skill execution, and system operations. These tools are protected by 33 granular scopes that follow a consistent {action}:{resource} naming pattern.
The scope design enables precise permission modeling. read:* scopes provide observability, write:* scopes allow configuration changes, and execute:* scopes permit active operations like completions and searches.
Core Scope Categories
| Pattern | Purpose | Example Scopes |
|---|---|---|
read:{resource} |
Observability and metrics | read:health, read:combos, read:quota, read:usage |
write:{resource} |
Configuration and mutation | write:combos, write:budget, write:resilience, write:cache |
execute:{action} |
Active operations | execute:completions, execute:search |
According to the OmniRoute source code in open-sse/mcp-server/schemas/tools.ts, each tool declares its required scopes in its Zod schema definition. The MCP_TOOL_MAP populated from these schemas drives runtime enforcement.
Scope Enforcement Implementation in scopeEnforcement.ts
The security model centers on two key functions in open-sse/mcp-server/scopeEnforcement.ts:
resolveCallerScopeContext
This function extracts caller scopes from three sources in order of precedence:
extra.authInfo.scopes— Authentication payload (highest priority)extra._meta.scopes— Tool call metadataOMNIROUTE_MCP_SCOPESenvironment variable — Fallback for local development
If no scopes are found, the caller receives an empty scope list and is treated as anonymous.
evaluateToolScopes
This function performs the actual authorization check with signature:
- Tool name lookup in
MCP_TOOL_MAP - Required scope retrieval
- Pattern matching via
scopeMatches(exact, wildcardread:*, prefixread:health*)
The function returns a structured result: { allowed: boolean, required: string[], provided: string[], missing: string[], reason?: string }.
Scope enforcement activates when OMNIROUTE_MCP_ENFORCE_SCOPES=true. When disabled, all calls proceed unchecked — useful for development but never for production.
Complete Tool-to-Scope Mapping
The following representative tools demonstrate how OmniRoute assigns scopes. The full catalog spans 33 distinct scope values.
| Scope | Representative Tools | File Reference |
|---|---|---|
read:health |
omniroute_get_health, omniroute_simulate_route, omniroute_get_provider_metrics |
README.md tool table |
read:combos |
omniroute_list_combos, omniroute_get_combo_metrics, omniroute_best_combo_for_task |
README.md tool table |
read:quota |
omniroute_check_quota |
README.md tool table |
read:usage |
omniroute_cost_report, omniroute_explain_route, omniroute_get_session_snapshot |
README.md tool table |
read:models |
omniroute_list_models_catalog |
README.md tool table |
read:cache |
omniroute_cache_stats |
README.md tool table |
read:compression |
omniroute_compression_status, omniroute_list_compression_combos |
README.md tool table |
write:combos |
omniroute_switch_combo, omniroute_create_combo |
README.md tool table |
write:budget |
omniroute_set_budget_guard |
README.md tool table |
write:resilience |
omniroute_set_resilience_profile |
README.md tool table |
write:cache |
omniroute_cache_flush |
README.md tool table |
write:compression |
omniroute_compression_configure, omniroute_set_compression_engine |
README.md tool table |
execute:completions |
omniroute_route_request, omniroute_test_combo |
README.md tool table |
execute:search |
omniroute_web_fetch, omniroute_web_search |
README.md tool table |
Additional scopes cover proxy operations, pricing management, catalog administration, and specialized memory and skill operations.
Accessing OmniRoute MCP Tools: Three Methods
Python Client with Automatic Scope Handling
The MCP Python SDK automatically includes caller scopes in tool invocations:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def demo():
server = StdioServerParameters(
command="npx",
args=["tsx", "open-sse/mcp-server/server.ts"],
env={"OMNIROUTE_BASE_URL": "http://localhost:20128"}
)
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as sess:
await sess.initialize()
# Requires `read:health` scope
health = await sess.call_tool("omniroute_get_health", {})
print("Health:", health.content[0].text)
# Fails without `write:combos` scope
try:
await sess.call_tool("omniroute_switch_combo", {
"comboId": "c1",
"active": True
})
except Exception as e:
print("Scope error:", e)
The open-sse/mcp-server/scopeEnforcement.ts validation runs automatically on each call.
Direct TypeScript Scope Inspection
For debugging or custom implementations, use the enforcement functions directly:
import {
resolveCallerScopeContext,
evaluateToolScopes
} from "./scopeEnforcement.ts";
const extra = {
authInfo: {
clientId: "agent-123",
scopes: ["read:health", "read:combos"]
},
sessionId: "sess-xyz",
};
const ctx = resolveCallerScopeContext(extra);
const check = evaluateToolScopes(
"omniroute_get_health",
ctx.scopes,
true // enforceScopes flag
);
console.log(
check.allowed
? "Allowed"
: `Missing: ${check.missing.join(", ")}`
);
This executes the same logic at lines 72-96 and 99-135 of scopeEnforcement.ts that the server uses internally.
HTTP API with Manual Scope Header
For direct HTTP integration, scopes pass via header:
curl -X POST http://localhost:20128/mcp \
-H "Content-Type: application/json" \
-H "X-OmniRoute-Scopes: read:health,read:quota" \
-d '{"tool":"omniroute_check_quota","args":{}}'
The server extracts X-OmniRoute-Scopes and processes through identical enforcement pipeline as stdio transport.
Audit Logging and Observability
Every tool invocation is recorded in open-sse/mcp-server/audit.ts. The implementation:
- SHA-256 hashes input arguments for privacy
- Stores truncated output previews
- Maintains SQLite-backed history for compliance tracing
This logging operates independently of scope enforcement, ensuring complete audit trails even when enforcement is disabled.
Key Source Files
Understanding OmniRoute's MCP server requires familiarity with these components:
| File | Responsibility |
|---|---|
open-sse/mcp-server/README.md |
Human-readable tool and scope documentation |
open-sse/mcp-server/scopeEnforcement.ts |
Core authorization logic (resolveCallerScopeContext, evaluateToolScopes, scopeMatches) |
open-sse/mcp-server/schemas/tools.ts |
Zod schemas defining tool signatures and required scopes |
open-sse/mcp-server/audit.ts |
SQLite audit logger with SHA-256 input hashing |
open-sse/mcp-server/server.ts |
Transport bootstrap (stdio/HTTP) and tool dispatcher |
open-sse/mcp-server/__tests__/essentialTools.test.ts |
Scope enforcement validation tests |
Summary
- OmniRoute's MCP server exposes 109 tools protected by 33 fine-grained scopes following
{action}:{resource}naming conventions - Scope enforcement occurs through
resolveCallerScopeContextextracting from auth payload, metadata, or environment, followed byevaluateToolScopesperforming pattern-matched validation - Three transport modes support scope passing: stdio (automatic), TypeScript SDK (programmatic), and HTTP (
X-OmniRoute-Scopesheader) - Development override via
OMNIROUTE_MCP_ENFORCE_SCOPES=falsedisables checks for local testing - Complete audit trail via
audit.tswith hashed inputs stored in SQLite
Frequently Asked Questions
How are the 33 scopes defined and where can I see the complete list?
The complete scope-to-tool mapping is documented in open-sse/mcp-server/README.md under the Security & Scope Enforcement section. The source of truth is open-sse/mcp-server/schemas/tools.ts, where each tool's Zod schema includes a scopes array. The README renders this as a readable table covering all 33 scopes from read:health through specialized scopes like execute:search and write:compression.
What happens when a tool call lacks required scopes?
The evaluateToolScopes function returns { allowed: false, missing: [...] } with a descriptive reason. When OMNIROUTE_MCP_ENFORCE_SCOPES=true, the server rejects the call before execution. The caller receives an error indicating which scopes are required versus which were provided. This check occurs at lines 99-135 of scopeEnforcement.ts.
Can I use wildcards or patterns in scope assignments?
Yes. The scopeMatches function supports three patterns: exact string match (read:health equals read:health), wildcard suffix (read:* matches any read scope), and prefix wildcards (read:health* matches read:health and read:health-metrics). This allows coarse-grained permission grants without enumerating every specific scope.
How do I add custom scopes for my organization's tools?
Extend open-sse/mcp-server/schemas/tools.ts with new tool definitions including your custom scopes array. The MCP_TOOL_MAP automatically incorporates these. Ensure your authentication system or environment configuration populates extra.authInfo.scopes or OMNIROUTE_MCP_SCOPES with your custom scope values. No changes to scopeEnforcement.ts are required — the pattern matching handles arbitrary scope strings.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →