How to Set Up MCP Server with Scoped Tool Permissions in OmniRoute
Configure the OMNIROUTE_MCP_SCOPES environment variable to map tools to required permission scopes, then deploy the MCP server with the scopeEnforcement.ts middleware to authorize every incoming request against the caller's JWT or API key claims.
The OmniRoute MCP (Multi-Channel Proxy) server exposes over 100 tools via HTTP, SSE, or stdio transports, but production deployments require strict access control. By setting up MCP server with scoped tool permissions, you can restrict which tools each client is allowed to invoke based on granular permission scopes defined in src/shared/constants/mcpScopes.ts.
Core Components of the Permission System
The permission model relies on three interconnected pieces that govern tool access from declaration to enforcement.
MCP_TOOL_SCOPES Mapping
The MCP_TOOL_SCOPES constant in src/shared/constants/mcpScopes.ts serves as the authoritative registry that lists every available tool alongside the specific scopes required to invoke it. When a tool is registered, the server consults this mapping to determine what permissions an incoming request must possess.
Scope Enforcement Middleware
Located at open-sse/mcp-server/scopeEnforcement.ts, this middleware runs on every inbound request and performs the actual authorization check. It extracts the caller's scopes from JWT claims (using the scp key) or API key metadata, then validates them against the requirements defined in MCP_TOOL_SCOPES. Failed validations return a 403 Forbidden response before the tool executes.
Declarative Scope Presets
The same constants file exports MCP_SCOPE_PRESETS, which provides pre-configured bundles like default (all tools), readOnly (safe read operations), and manage (administrative functions). These presets simplify configuration by grouping common permission patterns into single identifiers.
Step-by-Step Setup Guide
1. Install and Build the Server
Begin by installing dependencies and compiling the production bundle that includes the MCP server entry point.
npm ci
npm run build:release
The compiled entry point resides at open-sse/mcp-server/index.ts, which handles environment parsing and server initialization.
2. Configure Scoped Permissions
Choose between using a preset or defining a custom tool-to-scope mapping via the OMNIROUTE_MCP_SCOPES environment variable.
Option A: Use a Preset
OMNIROUTE_MCP_SCOPES=readOnly
Option B: Provide Custom JSON
OMNIROUTE_MCP_SCOPES='{
"omniroute_web_fetch": ["execute:search"],
"omniroute_memory_add": ["memory:write"]
}'
The server parses this JSON at startup (as implemented in open-sse/mcp-server/index.ts) to build the active permission matrix.
3. Start the MCP Server
Launch the server using the compiled output. By default, it listens on http://127.0.0.1:3000, configurable via MCP_SERVER_PORT.
node --import tsx/esm open-sse/mcp-server/index.js
4. Issue Scoped Client Tokens
For API Key Authentication: Add a scopes claim to the key's metadata using the OmniRoute dashboard or CLI (omniroute keys create).
For JWT Authentication: Include a scp claim listing the scopes the bearer possesses:
{
"sub": "user-123",
"scp": ["execute:search", "memory:write"]
}
5. Invoke Tools with Automatic Validation
When calling a tool endpoint, the scopeEnforcement.ts middleware automatically verifies the token against the tool's required scopes. Requests lacking authorization receive an immediate rejection.
Practical Implementation Examples
Running with a Custom Scope Map
Configure the environment to allow only web search and memory write operations:
export OMNIROUTE_MCP_SCOPES='{
"omniroute_web_fetch": ["execute:search"],
"omniroute_memory_add": ["memory:write"]
}'
Start the server:
node --import tsx/esm open-sse/mcp-server/index.js
Attempting Unauthorized Tool Access
If a client presents a JWT without the required scope:
{
"sub": "user-123",
"scp": ["memory:write"]
}
And attempts to call omniroute_web_fetch (which requires execute:search), the server responds:
{
"error": "Forbidden",
"message": "Missing required scope for tool omniroute_web_fetch"
}
Deploying a Read-Only Environment
Restrict clients to safe, non-destructive operations using the built-in preset:
OMNIROUTE_MCP_SCOPES=readOnly
This preset, defined in src/shared/constants/mcpScopes.ts, grants access only to tools like list_models_catalog and search while blocking any write or execute operations.
Summary
- The OmniRoute MCP server exposes tools through
open-sse/mcp-server/index.tswith permission enforcement handled byscopeEnforcement.ts. - Tool permissions are declared in
src/shared/constants/mcpScopes.tsvia theMCP_TOOL_SCOPESmapping andMCP_SCOPE_PRESETS. - Configure scope restrictions using the
OMNIROUTE_MCP_SCOPESenvironment variable, accepting either preset names or custom JSON mappings. - Client authentication requires JWT tokens with an
scpclaim or API keys with embedded scope metadata. - Failed scope validation results in a 403 Forbidden response, preventing unauthorized tool execution.
Frequently Asked Questions
How do I restrict a client to read-only tools?
Set OMNIROUTE_MCP_SCOPES=readOnly in your environment configuration. This preset, defined in src/shared/constants/mcpScopes.ts, automatically restricts access to safe read operations like list_models_catalog while blocking write and execute tools.
What HTTP status code is returned for insufficient permissions?
The scopeEnforcement.ts middleware returns a 403 Forbidden status with a JSON error message indicating the missing scope. This occurs before the tool handler executes, ensuring no unauthorized side effects.
Can I use both presets and custom scope mappings simultaneously?
No, the configuration accepts either a preset identifier (like default or readOnly) or a custom JSON object via OMNIROUTE_MCP_SCOPES. You must choose one approach per deployment as implemented in open-sse/mcp-server/index.ts.
Where is the scope validation logic implemented?
Scope validation resides in open-sse/mcp-server/scopeEnforcement.ts, which acts as middleware on every request. This file extracts scopes from the JWT scp claim or API key metadata and validates them against the MCP_TOOL_SCOPES mapping from src/shared/constants/mcpScopes.ts.
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 →