OpenRouter MCP

MCP server for OpenRouter — chat with any model through one API key

Documentation

mcp-server-open-router

License: MIT Rust edition 2024 MCP OpenRouter

An MCP (Model Context Protocol) server for OpenRouter — one API key, 300+ models from every major lab. Built in Rust, it exposes chat, vision, web-search, model listing, and credit-balance tools over stdio so any MCP client can use them.

Default model: moonshotai/kimi-k3 — 1M context, $3/$15 per M input/output, vision-capable. Communicates via stdio using JSON-RPC 2.0. Structurally it mirrors mcp-server-fable with the OpenAI-compatible request layer of mcp-server-grok-chat.

OpenRouter specifics

  • Actual-cost accounting — every chat request sends usage:{"include":true}; the response footer shows OpenRouter's reported USD ([cost: $0.008901]), never an estimate from pricing constants.
  • Error-in-200 handling — OpenRouter can return HTTP 200 with a top-level {"error":...} body (no choices). The server treats that as a tool error, not a panic or empty success. Per-choice provider errors render inline.
  • Unified reasoning — request field reasoning with effort / exclude / enabled; optional [reasoning]…[/reasoning] block when show_reasoning=true.
  • Web plugin + Sourceschat_with_search uses plugins:[{"id":"web"}]; cited pages become a Sources: list from url_citation annotations.
  • Unsupported params are silently dropped — e.g. kimi-k3 does not support temperature; sending it is always safe.
  • Attribution headers — optional app_nameX-Title, site_urlHTTP-Referer.

Tools

ToolDescription
chatChat with any OpenRouter model. Multi-turn history, system prompt, structured output via JSON schema, reasoning control. Token + actual USD cost footer.
chat_with_visionAnalyse an image (http(s) URL, data URL, or local file path). Default model accepts images.
chat_with_searchWeb-grounded chat via OpenRouter's web plugin. Returns answer + Sources: list.
list_modelsFilterable catalog with context length and $/M pricing (cached 5 minutes).
creditsAccount balance: purchased, used, remaining.

chat

NameTypeRequiredDescription
promptstringyesThe user message / prompt to send
system_promptstringnoOptional system prompt to set context/behaviour
messagesstringnoFull conversation history as a JSON array of {role, content} objects. When provided, prompt is appended as the final user message.
modelstringnoModel ID (default: configured default / moonshotai/kimi-k3). Call list_models to browse.
temperaturenumbernoSampling temperature (0.0–2.0). Models that don't support it silently ignore it.
max_tokensintegernoMaximum tokens to generate
reasoning_effortstringnolow / medium / high for reasoning-capable models. Hidden unless show_reasoning=true.
show_reasoningbooleannoInclude reasoning text as a [reasoning] block (default false)
response_schemastringnoOptional JSON schema string to enforce structured output

chat_with_vision

NameTypeRequiredDescription
promptstringyesText prompt describing what to analyse in the image
imagestringyeshttp(s) URL, data URL, or local file path (png/jpg/jpeg/webp/gif, max 20 MB)
detailstringnolow / high / auto (default auto)
modelstringnoMust be vision-capable; default kimi-k3 accepts images
temperaturenumbernoSampling temperature (0.0–2.0)
max_tokensintegernoMaximum tokens to generate

chat_with_search

NameTypeRequiredDescription
promptstringyesThe user message / prompt
system_promptstringnoOptional system prompt
modelstringnoModel ID (default: configured default)
max_resultsintegernoMax web results, 1–20 (default 5). ~$0.004 each
temperaturenumbernoSampling temperature (0.0–2.0)
max_tokensintegernoMaximum tokens to generate

list_models

NameTypeRequiredDescription
filterstringnoCase-insensitive substring over model id and name. Omit to list all (~344 models).

credits

No parameters.

Prerequisites

The server expects a config file at ~/.config/mcp-server-open-router/config.toml containing at minimum your api_key. See config.toml.example.

api_key = "sk-or-..."

# Optional overrides:
# base_url = "https://openrouter.ai/api/v1"
# default_model = "moonshotai/kimi-k3"
# default_max_tokens = 8192
# app_name = "mcp-server-open-router"
# site_url = "https://example.com"

The server fails fast at startup if the config is missing or api_key is empty.

Build

cargo build --release   # produces target/release/open-router
cargo build             # debug build
cargo run               # run in dev mode
RUST_LOG=debug cargo run
cargo test              # unit tests (Display formatter, builders, mockito round-trips)

Installation & MCP Configuration

1. Build the server

cargo build --release
# The binary will be at: target/release/open-router

Use the full absolute path to target/release/open-router in all configuration below.

2. AI-assisted installation (recommended modern method)

Copy the block below and paste it directly to your AI coding assistant (Claude Code, Cursor, Grok, etc.). The AI will handle cloning (if needed), building, path resolution, and registration for you.

Add the mcp-server-open-router MCP server for me.

Repository: https://github.com/<your-username>/mcp-server-open-router   (update this URL if you have a fork)

Steps to perform:
1. If the repo isn't cloned locally yet, clone it and cd into it.
2. Build the release binary:
     cargo build --release
3. Determine the absolute path to the built binary (target/release/open-router).
4. Set up the config directory and file:
     mkdir -p ~/.config/mcp-server-open-router
     cp config.toml.example ~/.config/mcp-server-open-router/config.toml
   Then edit the config and add your OpenRouter API key (api_key = "sk-or-...").

5. Register it as an MCP server named "open-router".

   For Claude Code, run:
     claude mcp add open-router -- <ABSOLUTE_PATH_TO>/target/release/open-router

   For Claude Desktop or other MCP clients, add this under the "mcpServers" key (use the real absolute path):
{
  "open-router": {
    "command": "<ABSOLUTE_PATH_TO>/target/release/open-router"
  }
}

After setup, test that the `chat` and `credits` tools are available and working.

3. Manual configuration

Claude Desktop or any MCP client (~/.config/Claude/claude_desktop_config.json or equivalent):

{
  "mcpServers": {
    "open-router": {
      "command": "/media/codechap/4TB/develop/mcps/mcp-server-open-router/target/release/open-router"
    }
  }
}

Claude Code (one-liner):

claude mcp add open-router -- /media/codechap/4TB/develop/mcps/mcp-server-open-router/target/release/open-router

Replace the path with your actual absolute path to the release binary.

Usage

Once registered, an MCP client calls the tools by name.

From an MCP client (e.g. Claude Code)

Use the open-router chat tool. prompt: "Reply with exactly OK". max_tokens: 10

Raw JSON-RPC over stdio

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
  "name":"chat",
  "arguments":{
    "prompt":"Reply with exactly OK",
    "max_tokens":10
  }}}

Every successful chat response ends with token-usage and actual-cost footers:

OK
[finish_reason: stop]
[model: moonshotai/kimi-k3 via Moonshot AI]
[tokens: 812 prompt + 431 completion = 1243 total; 640 cached; 210 reasoning]
[cost: $0.008901]

The cost line is OpenRouter-reported USD (because every request opts into usage.include), not an estimate from pricing constants.

Project Structure

src/
  main.rs    - entry point, config loading, stdio transport setup
  server.rs  - MCP tools (chat, chat_with_vision, chat_with_search, list_models, credits) + helpers
  api.rs     - OpenRouter HTTP client, request/response types, Display formatter
  params.rs  - tool parameter types with serde + JSON Schema derives
  config.rs  - TOML config loading

License

MIT