# How to Set Up MCP Server with Scoped Tool Permissions in OmniRoute

> Learn to set up an MCP server with scoped tool permissions in OmniRoute. Configure OMNIROUTE_MCP_SCOPES and deploy scopeEnforcement.ts middleware for secure access.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-28

---

**Configure the `OMNIROUTE_MCP_SCOPES` environment variable to map tools to required permission scopes, then deploy the MCP server with the [`scopeEnforcement.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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.

```bash
npm ci
npm run build:release

```

The compiled entry point resides at [`open-sse/mcp-server/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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**

```bash
OMNIROUTE_MCP_SCOPES=readOnly

```

**Option B: Provide Custom JSON**

```bash
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`.

```bash
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:

```json
{
  "sub": "user-123",
  "scp": ["execute:search", "memory:write"]
}

```

### 5. Invoke Tools with Automatic Validation

When calling a tool endpoint, the [`scopeEnforcement.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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:

```bash
export OMNIROUTE_MCP_SCOPES='{
  "omniroute_web_fetch": ["execute:search"],
  "omniroute_memory_add": ["memory:write"]
}'

```

Start the server:

```bash
node --import tsx/esm open-sse/mcp-server/index.js

```

### Attempting Unauthorized Tool Access

If a client presents a JWT without the required scope:

```json
{
  "sub": "user-123",
  "scp": ["memory:write"]
}

```

And attempts to call `omniroute_web_fetch` (which requires `execute:search`), the server responds:

```json
{
  "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:

```bash
OMNIROUTE_MCP_SCOPES=readOnly

```

This preset, defined in [`src/shared/constants/mcpScopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/index.ts) with permission enforcement handled by [`scopeEnforcement.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/scopeEnforcement.ts).
- **Tool permissions** are declared in [`src/shared/constants/mcpScopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/mcpScopes.ts) via the `MCP_TOOL_SCOPES` mapping and `MCP_SCOPE_PRESETS`.
- Configure **scope restrictions** using the `OMNIROUTE_MCP_SCOPES` environment variable, accepting either preset names or custom JSON mappings.
- **Client authentication** requires JWT tokens with an `scp` claim 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/mcp-server/index.ts).

### Where is the scope validation logic implemented?

Scope validation resides in [`open-sse/mcp-server/scopeEnforcement.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/constants/mcpScopes.ts).