Skip to main content
Glama
OpenRouter MCP Server

OpenRouter MCP Server

by vmhq

OpenRouter MCP Server

远程 MCP 服务器(流式 HTTP,无状态 JSON),让 AI 代理通过 OpenRouter API 将任务委托给更便宜的模型,查询目录和实时价格,并通过 .env 文件配置成本策略。

功能

  • 实时目录:查询 OpenRouter 的 GET /api/v1/models(带 5 分钟缓存),并暴露每百万 token 的美元价格、上下文窗口和工具调用支持。

  • 显式委托:代理根据价格选择模型并委托任务。

  • 基于价格的自动委托:服务器根据层级(economy / balanced / quality)使用可配置的价格区间选择模型。

  • 通过 .env 配置策略:最高价格上限、允许/阻止的模型列表、默认模型、首选提供商。

  • 真实成本:每次委托都返回使用的 token 和估算的美元成本。

Related MCP server: frugal

安装

npm install
cp .env.example .env   # edit and set your OPENROUTER_API_KEY
npm run build
npm start              # listens on http://localhost:3000/mcp

对于开发,自动重载:npm run dev。

Docker

一个多架构镜像(linux/amd64、linux/arm64)由 GitHub Actions 自动构建并发布到 GHCR:

ghcr.io/vmhq/openrouter-mcp-server

可用标签:latest(主分支)、vX.Y.Z / X.Y(发布版)、main 和 sha-<commit>。

Docker Compose

services:
  openrouter-mcp:
    image: ghcr.io/vmhq/openrouter-mcp-server:latest
    container_name: openrouter-mcp
    restart: unless-stopped
    ports:
      - "3000:3000"
    env_file:
      - .env
    volumes:
      # Persists OAuth state (registered clients, token hashes)
      - ./data:/app/data
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
docker compose up -d

注意:容器以非特权 node 用户运行。确保挂载的 ./data 目录对 UID 1000 可写(chown -R 1000:1000 ./data),否则无法持久化 OAuth 状态。

示例 .env

# --- Required ---
# Your OpenRouter API key (https://openrouter.ai/keys)
OPENROUTER_API_KEY=sk-or-v1-...

# --- HTTP server ---
# Port where the MCP endpoint is exposed (http://host:PORT/mcp)
PORT=3000
# Optional static bearer token. If set, MCP clients must send
# "Authorization: Bearer <token>". Strongly recommended if the server
# is reachable outside localhost.
MCP_AUTH_TOKEN=

# --- Interactive OAuth with PocketID (for AI agents like Claude) ---
# Public URL of this server (e.g. https://mcp.example.com). Required so the
# OAuth metadata and callback point to the right URL behind a reverse proxy.
MCP_PUBLIC_URL=
# When all three POCKETID_* variables are set, the /oauth/authorize flow
# delegates the human login to your PocketID instance (passkey).
# In PocketID: create an OIDC client and register this callback:
#   <MCP_PUBLIC_URL>/oauth/callback
POCKETID_ISSUER=
POCKETID_CLIENT_ID=
POCKETID_CLIENT_SECRET=
# Optional OIDC scopes (space-separated). Default: "openid profile email".
# POCKETID_SCOPES=openid profile email
# Path of the file where OAuth state is persisted (registered clients,
# one-time codes, and token hashes). Default: ./data/oauth-state.json
# MCP_OAUTH_STATE_PATH=./data/oauth-state.json
# OAuth access token lifetime, in seconds. Default: 2592000 (30 days).
# MCP_OAUTH_TOKEN_TTL_S=2592000

# --- Optional OpenRouter attribution (rankings) ---
APP_URL=
APP_TITLE=OpenRouter MCP Server

# --- Delegation policy ---
# Default model when the agent doesn't specify one in openrouter_delegate_task
DEFAULT_MODEL=

# Price caps (USD per million tokens). Models above them are rejected
# with an explanatory error. Empty = no limit.
MAX_PROMPT_PRICE_PER_M=
MAX_COMPLETION_PRICE_PER_M=

# Comma-separated control lists. Accept exact ids ("openai/gpt-4.1-mini")
# or provider prefixes ("openai/"). Empty ALLOWED_MODELS = all allowed
# (except blocked ones).
ALLOWED_MODELS=
BLOCKED_MODELS=

# Allow free models (price 0)? They usually have strict rate limits.
ALLOW_FREE_MODELS=true

# Preferred providers for automatic selection (openrouter_auto_delegate)
PREFERRED_PROVIDERS=openai,anthropic,google,meta-llama,mistralai,deepseek,qwen,x-ai,amazon

# "Combined" price caps (70% prompt + 30% completion, USD/M tokens)
# for each tier of the automatic selection.
TIER_ECONOMY_MAX_PRICE=0.5
TIER_BALANCED_MAX_PRICE=3
TIER_QUALITY_MAX_PRICE=15

# Model catalog cache, in seconds
MODELS_CACHE_TTL_SECONDS=300

环境变量

参见 .env.example — 主要变量如下:

变量

描述

OPENROUTER_API_KEY

必需。 你的密钥来自 https://openrouter.ai/keys

PORT

HTTP 端口(默认 3000)

MCP_AUTH_TOKEN

如果设置,客户端必须发送 Authorization: Bearer <token>。如果你将服务器暴露在 localhost 之外,则实际上必须设置。

MCP_PUBLIC_URL

服务器的公共 URL(例如 https://mcp.example.com);在反向代理后面进行 OAuth 流程时需要

POCKETID_ISSUER / POCKETID_CLIENT_ID / POCKETID_CLIENT_SECRET

通过将身份验证委托给你的 PocketID 实例来启用交互式 OAuth 登录(见下文)

DEFAULT_MODEL

当代理未指定模型时,openrouter_delegate_task 使用的模型

MAX_PROMPT_PRICE_PER_M / MAX_COMPLETION_PRICE_PER_M

价格上限(美元/百万 token);更贵的模型将被拒绝

ALLOWED_MODELS / BLOCKED_MODELS

逗号分隔的列表:精确 ID 或前缀(openai/)

ALLOW_FREE_MODELS

允许免费模型(默认 true)

TIER_*_MAX_PRICE

自动选择中每个层级的组合价格上限(0.7·输入 + 0.3·输出)

暴露的工具

工具

描述

openrouter_list_models

列出带有实时价格的模型;按文本、价格、上下文、工具调用过滤;按价格/上下文/新近度排序;分页

openrouter_get_model

模型的完整详情 + .env 策略是否允许它

openrouter_delegate_task

将任务委托给特定模型;返回响应、token 和估算成本

openrouter_auto_delegate

服务器按价格层级(economy/balanced/quality)选择模型并委托

openrouter_check_credits

已配置 API 密钥的使用情况和限制

典型代理流程:openrouter_list_models(或直接使用 economy 层级的 openrouter_auto_delegate)→ 委托任务 → 使用响应,并知道其成本。

重要:被委托的模型看不到代理的对话;任务(task)必须是自包含的,包含所有必要的上下文。

连接代理

Claude Code:

claude mcp add --transport http openrouter http://localhost:3000/mcp

使用认证令牌:

claude mcp add --transport http openrouter http://YOUR_HOST:3000/mcp --header "Authorization: Bearer YOUR_TOKEN"

任何 MCP 客户端:将其指向 POST /mcp 端点,使用“流式 HTTP”传输。有一个 GET /health 端点用于监控。

claude.ai(远程连接器):需要公共 HTTPS URL — 将服务器部署在反向代理(Caddy/nginx)后面的 VPS 上,或使用隧道(例如 cloudflared tunnel)。启用 OAuth 后(见下文),添加指向 https://YOUR_HOST/mcp 的连接器,并将高级 OAuth 客户端 ID/密钥字段留空:服务器发布 OAuth 元数据并支持动态客户端注册,因此当你点击授权时,Claude 会自动注册并获取其令牌。

使用 PocketID 的 OAuth

服务器为 AI 代理(Claude、Cursor 等)实现完整的 OAuth 2.1:它充当 MCP 客户端的授权服务器(RFC 7591 动态客户端注册 + PKCE S256 + 颁发自己的令牌,带有 RFC 8414/9728 元数据),并通过 OIDC(passkey)将人类登录委托给你的 PocketID 实例。

流程:MCP 客户端收到带有 WWW-Authenticate 的 401 → 在 /.well-known/oauth-protected-resource 发现元数据 → 在 /oauth/register 注册 → 在浏览器中打开 /oauth/authorize → 用户使用其 passkey 登录 PocketID → PocketID 返回到 /oauth/callback → 服务器颁发自己的代码,客户端在 /oauth/token 将其交换为访问令牌(默认 30 天)。

设置:

  1. 在 PocketID 中,创建一个新的 OIDC 客户端。

  2. 注册回调:<MCP_PUBLIC_URL>/oauth/callback。

  3. 使用 PocketID 中 OIDC 客户端的允许组来限制谁可以登录。

  4. 将客户端 ID 和客户端密钥复制到 POCKETID_CLIENT_ID / POCKETID_CLIENT_SECRET,并在 POCKETID_ISSUER 中设置 PocketID 基础 URL。

  5. 将 MCP_PUBLIC_URL 设置为服务器的公共 HTTPS URL。

如果未设置 POCKETID_* 变量,交互式 /oauth/authorize 流程会显示错误;静态的 MCP_AUTH_TOKEN 承载令牌可并行用于机器对机器访问(curl、Codex 等)。

OAuth 状态(已注册的客户端、一次性代码和令牌的 SHA-256 哈希 — 绝不是明文令牌)持久化到 ./data/oauth-state.json(可通过 MCP_OAUTH_STATE_PATH 配置)。如果连接器在状态被清除后重启失败,请在 Claude 中删除它并重新添加,以便它重新注册。

openrouter_auto_delegate 如何选择模型

  1. 根据 .env 策略和调用的要求(require_tools、min_context、文本输出)过滤目录。

  2. 计算每个模型的组合价格:0.7·input_price + 0.3·output_price(美元/百万 token)。

  3. 根据层级,在其价格区间内搜索(如果为空则回退到相邻区间):

    • economy(默认 ≤ $0.5/M):最便宜。

    • balanced($0.5–$3/M):中间区间中最便宜的。

    • quality($3–$15/M):上限内价格最高的(以价格作为能力的代理,但不达到旗舰模型)。

  4. 优先选择 PREFERRED_PROVIDERS 中的提供商,并在响应中报告所选模型、推理过程和被丢弃的备选方案。

安全

  • OpenRouter API 密钥仅存在于服务器的 .env 中;绝不会暴露给代理。

  • .env 文件位于 .gitignore 中。

  • 如果端口可从外部访问,请设置 MCP_AUTH_TOKEN 并通过 HTTPS 提供服务。

Related MCP Connectors

Related MCP Servers