MCP Router

repository·main·Indexed 24 days ago

https://github.com/mcp-router/mcp-router

A desktop application and set of tools for managing Model Context Protocol (MCP) servers. It features a centralized dashboard for organizing servers into projects and workspaces, managing tool availability, and monitoring logs. The ecosystem includes the @mcp_router/cli for bridging stdio and HTTP transports, @mcp_router/remote-api-types for tRPC client/server communication, and @mcp_router/tailwind-config for shared design system themes.

Tokens
38.8K
Snippets
101
Records
175
Agent score
85%

What's inside mcp-router

  1. Overview of MCP Router

    main

    MCP Router is a desktop application designed to simplify the management of Model Context Protocol (MCP) servers. It acts as a centralized hub for connecting, managing, and monitoring various MCP servers, allowing you to integrate them seamlessly with AI tools like Claude, Cline, Windsurf, and Cursor.

    Key capabilities include:

    • Universal Connectivity: Connect to both local and remote MCP servers using various protocols (DXT, JSON, Manual, etc.).
    • Context Management: Organize MCP servers into "Projects" and manage different configurations using "Workspaces" (similar to browser profiles).
    • Granular Control: Enable or disable specific tools at the individual server level.
    • Observability: Monitor detailed request logs and usage statistics.
    • Privacy-First: All request logs, configurations, and server data are stored locally on your device. API keys and credentials are never transmitted externally.
  2. Security hardening implemented in the 2026-06-24 PR

    main

    The following security improvements have been implemented to harden the MCP Router environment:

    • CLI HTTP Server: By default, the CLI HTTP server binds only to 127.0.0.1. If you need to expose it externally, the --token flag is now mandatory.
    • Remote MCP URL Validation: Remote MCP URLs are strictly validated for https, FQDN, DNS resolution, and redirects. Connections to localhost, private, or reserved IP addresses are rejected to prevent SSRF.
    • Encrypted Token Storage: MCP server bearer tokens and desktop authentication tokens are encrypted using Electron safeStorage where available.
    • Token Expiration: Shared tokens include an expiresAt field. For compatibility with existing MCP clients, expired tokens are not rejected during authentication or server access; invalidation must be performed via explicit revoke or regeneration.
    • Access Control: Adding new servers or performing a sync no longer automatically grants server access to existing tokens.
    • Header Validation: HTTP authorization and project headers are validated for single values, length, and control characters. The Authorization header accepts both raw tokens and the Bearer <token> format.
    • Skill Directory Security: Skill directory operations are confined to the storage directory, and symlinks are rejected during import.
    • Workflow & Redaction: Workflows that contain circular graphs are rejected before saving/enabling. Sensitive values like tokens, API keys, and passwords are redacted from Hook contexts and execution results.
  3. How tool discovery and execution works

    main

    MCP Router uses a centralized service to manage tool access across multiple MCP servers.

    Search Flow

    1. The client calls tool_discovery via MCP with a token and projectId.
    2. The ToolCatalogService collects the list of tools from all currently running servers via listTools.
    3. The service filters this list based on tool_permissions, projectId, and serverStatusMap (ensuring only authorized, active tools are visible).
    4. The filtered list is sent to the search provider:
      • Cloud Search (Priority): Attempts to use the Cloud Search API.
      • Local BM25 (Fallback): If the cloud search fails or is unavailable, it falls back to a local BM25 search.
    5. The ranked results are returned to the client.

    Execution Flow

    1. The client calls tool_execute with a toolKey (format: serverId:toolName).
    2. The router validates the request against TokenValidator, toolPermissions, serverStatusMap, and projectId.
    3. If valid, the request is delegated to the specific target server's tools/call method.
  4. Understand the Projects concept in MCP Router

    main

    Projects are a workspace-scoped organizational feature used to group and filter MCP servers.

    Key characteristics:

    • Single Assignment: Each server belongs to at most one project. If a server is not assigned to a project, it belongs to the Unassigned group.
    • Unassigned Group: Servers with no projectId are treated as Unassigned. In the API, this is represented by the constant UNASSIGNED_PROJECT_ID ("__unassigned__").
    • Project Deletion: Deleting a project automatically deletes all servers assigned to that project. They are not reassigned to the Unassigned group.
    • Scope: Projects are stored in the local workspace database. Remote workspaces may not support project UI and will degrade gracefully.
  5. Understand Cloud Sync with End-to-End Encryption (E2EE)

    main

    MCP Router provides a Cloud Sync mechanism that allows users to synchronize their MCP server configurations across multiple devices securely.

    Key Concepts:

    • E2EE (End-to-End Encryption): All sensitive data (like bearerToken, env, and remoteUrl) is encrypted locally before being sent to the cloud. The cloud provider cannot decrypt this data.
    • All-or-Nothing Sync: Instead of syncing individual servers, the system bundles all workspace information and server configurations into a single encrypted JSON blob. Syncing is a full replacement of the local state with the remote state (or vice versa).
    • Conflict Resolution: Conflicts are resolved using a Last-Write-Wins (LWW) strategy based on server timestamps. The version with the most recent updatedAt timestamp is preserved.
    • Security Model: Encryption keys are derived from a user-provided passphrase using Argon2id. If the passphrase is lost, the encrypted data cannot be recovered.
  6. Implement entity mapping for database rows

    main

    Repositories must handle the translation between database rows (often using snake_case and serialized JSON) and application entities (using camelCase and native types). This is achieved by implementing mapRowToEntity and mapEntityToRow within your repository.

    // Database row -> Entity
    protected mapRowToEntity(row: any): Entity {
      return {
        id: row.id,
        isActive: row.is_active === 1,
        metadata: JSON.parse(row.metadata || '{}'),
        createdAt: new Date(row.created_at)
      };
    }
    
    // Entity -> Database row
    protected mapEntityToRow(entity: Entity): Record<string, any> {
      return {
        id: entity.id,
        is_active: entity.isActive ? 1 : 0,
        metadata: JSON.stringify(entity.metadata),
        created_at: entity.createdAt.toISOString()
      };
    }
  7. Manage MCP Server Tool Permissions

    main

    MCP Router allows users to enable or disable individual tools from an MCP server via the Electron UI. This is managed through the server detail sheet, where tool permissions are persisted so that disabled tools remain inactive across application restarts.

    Key Concepts

    • Tool Permissions Map: A Record<string, boolean> where the key is the tool name and the value is its enabled/disabled state.
    • Persistence: Permissions are stored in the tool_permissions column of the servers database table.
    • Runtime Enforcement: The router filters disabled tools from aggregated listings and rejects invocation attempts for disabled tools with an InvalidRequest error.
  8. Configure MCP server execution via mcp_config

    main

    The mcp_config object within the server block defines how the host application executes your MCP server. This replaces the need for users to manually edit MCP configuration files.

    Supported Server Types

    1. node: Requires server.type = "node" and an entry_point pointing to a JavaScript file. Dependencies should be bundled in node_modules.
    2. python: Requires server.type = "python" and an entry_point pointing to a Python file. Dependencies must be bundled (e.g., in server/lib or server/venv).
    3. binary: Requires server.type = "binary" and an entry_point pointing to a pre-compiled executable. These are self-contained and do not require runtime specifications.

    Variable Substitution

    To ensure portability, use the following variables in your mcp_config paths and environment variables:

    • ${__dirname}: Absolute path to the extension's directory.
    • ${HOME}: User's home directory.
    • ${DESKTOP}: User's desktop directory.
    • ${DOCUMENTS}: User's documents directory.
    • ${DOWNLOADS}: User's downloads directory.
    • ${pathSeparator} or ${/}: The platform's path separator.
    • ${user_config.<key>}: Values collected from the user via the user_config schema.
    "mcp_config": {
      "command": "node",
      "args": ["${__dirname}/server/index.js"],
      "env": {
        "API_KEY": "${user_config.api_key}"
      }
    }
  9. Understand the MCP Router Database Architecture

    main

    MCP Router uses a multi-layered database architecture designed for Electron applications. It leverages SQLite with the better-sqlite3 driver for high performance and ACID compliance. The architecture is built around three core patterns to ensure type safety, maintainability, and consistency across multiple workspaces:

    1. Repository Pattern: Encapsulates data access logic for specific entities (e.g., servers, logs, settings) by extending a BaseRepository.
    2. Factory Pattern: Centralizes the creation and management of repository instances via RepositoryFactory, ensuring that repository instances are correctly reset when switching between different database connections.
    3. Context Pattern: Manages the current active database connection through DatabaseContext, providing a consistent way to access the workspace-specific database throughout the application.

    This design allows the application to support multiple independent workspaces, where each workspace has its own dedicated SQLite database file.

  10. How multi-workspace database separation works

    main

    MCP Router implements workspace isolation by using two distinct types of SQLite databases:

    • Main Database (mcprouter.db): Stores global configuration and workspace metadata (e.g., a list of available workspaces).
    • Workspace Database (workspace-{id}.db): A dedicated database file for each specific workspace containing its unique data (e.g., servers, logs, and tokens).

    Switching Workspaces: When a user switches workspaces, the system performs the following lifecycle:

    1. Closes the current database connection.
    2. Opens the new workspace's database file.
    3. Triggers RepositoryFactory to reset all existing repository instances.
    4. Re-instantiates repositories using the new database connection.
  11. E2E Test Best Practices

    main

    Follow these guidelines to maintain a healthy test suite:

    1. Element Selection: Use data-testid attributes for reliable element selection.
    2. Atomicity: Keep tests independent and atomic.
    3. Naming: Use descriptive test names.
    4. Cleanup: Clean up test data after tests complete.
    5. Reusability: Use page objects for reusable interactions.