dxt-openrouter-router
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dxt-openrouter-routerroute research_long_context low energy"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
DXT OpenRouter Router
A tiny MCP (stdio) server that returns a ready-to-send OpenRouter request body from a named preset and your current energy budget:
| Model slug becomes | Meaning |
|
| cheapest provider serving that model |
|
| the model's default provider |
|
| highest-throughput provider |
Two things make this different from a normal cost router:
It routes on energy, not just cost. The input is a fact about you, not about the task. "Cheap" and "fast" are the same axis viewed from different energy levels.
Zero Data Retention is the default. Every body ships
provider.data_collection: "deny", so a preset has to explicitly opt out of privacy rather than opt in to it.
It builds the request. It does not send it — so it never needs your API key in-process, and never sees a response.
Install
npm install -g dxt-openrouter-routerOr run it without installing:
npx dxt-openrouter-routerRelated MCP server: mcp-openrouter
Register it with an MCP host
Claude Desktop (claude_desktop_config.json) or any MCP client:
{
"mcpServers": {
"openrouter-router": {
"command": "npx",
"args": ["-y", "dxt-openrouter-router"],
"env": {
"ROUTING_PRESETS_PATH": "C:\\path\\to\\routing.presets.json"
}
}
}
}ROUTING_PRESETS_PATH is optional — omit it and the bundled routing.presets.json is used. The file is re-read on every call, so you can edit presets without restarting the host.
The routeLLM tool
Argument | Required | Description |
| ✅ | A key from |
|
| |
| The user message to place in the body | |
| Overrides the preset's own system prompt | |
| Extra body fields merged in last, e.g. |
Example
// call
{ "preset": "research_long_context", "energy": "low", "user_prompt": "Synthesize these sources..." }// result
{
"url": "https://openrouter.ai/api/v1/chat/completions",
"method": "POST",
"headers": {
"Authorization": "Bearer $OPENROUTER_API_KEY", // literal placeholder — never your real key
"Content-Type": "application/json"
},
"api_key_configured": true,
"body": {
"temperature": 0.2,
"model": "meta-llama/llama-3.1-70b-instruct:floor",
"messages": [
{ "role": "system", "content": "You are a careful research synthesist. ..." },
{ "role": "user", "content": "Synthesize these sources..." }
],
"provider": { "data_collection": "deny" }
}
}Presets
routing.presets.json is a plain map of name → preset:
{
"presets": {
"daily_driver": {
"model": "google/gemini-3.6-flash", // no :floor/:nitro here — energy adds that
"description": "Default workhorse — unit tests, refactors, docs, CLI loops.",
"system": "Optional default system prompt.",
"provider": { "data_collection": "deny" }, // merged over the ZDR default
"response_format": { "type": "json_object" }, // passed straight through
"params": { "temperature": 0.4 } // any other OpenRouter body field
}
}
}Bundled presets mirror a simple decision tree:
Preset | Model | Reach for it when |
|
| formats, clarifications, vibe checks |
|
| ~80% of volume — tests, refactors, docs |
|
| math, symbolic logic, formal reasoning |
|
| architecture, nuanced review, agentic work |
|
| long-context synthesis across sources |
|
| extraction that must return parseable JSON |
Slugs were verified against https://openrouter.ai/api/v1/models on 2026-07-22. OpenRouter slugs change as models ship — re-check before relying on them.
Secrets
🔒 This package contains no API key, and the tool output never includes one.
OPENROUTER_API_KEYis read from the environment, and only ever reported as the booleanapi_key_configured.The
Authorizationheader is emitted as the literal stringBearer $OPENROUTER_API_KEY, so tool output is safe to paste into a chat log, an issue, or a commit.Copy
.env.example→.envfor local use..envis gitignored.
Use as a library
The pure core is exported, so you can build bodies without MCP:
import { buildRequestBody, loadPresets } from "dxt-openrouter-router";
const presets = loadPresets("./routing.presets.json");
const body = buildRequestBody(presets, { preset: "daily_driver", energy: "low" });Develop
npm install
npm run build # tsc -> dist/
npm test # node --test test/License
MIT © Sasha Philius
Available Tools
1 toolrouteLLMA
Build a ready-to-send OpenRouter chat-completion request body from a named preset and the user's current energy budget. energy=low appends :floor (cheapest provider), energy=high appends :nitro (highest throughput), energy=balanced uses the base model slug. Zero Data Retention (provider.data_collection=deny) is on by default. Returns the URL, headers and body — it does NOT send the request.
| Name | Required | Description | Default |
|---|---|---|---|
| energy | No | Your current energy budget. low = cheapest (:floor), high = fastest (:nitro), balanced = the model's default provider. | balanced |
| preset | Yes | Name of a preset from routing.presets.json, e.g. 'research_long_context'. | |
| system | No | Overrides the preset's own system prompt when supplied. | |
| overrides | No | Extra OpenRouter body fields merged in last, e.g. { "temperature": 0.2 }. | |
| user_prompt | No | The user message to place in the request body. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and communicates key behavior well: it explicitly states Zero Data Retention default, the energy-based provider suffix logic, and the crucial fact that it does NOT send the request. The one gap is not disclosing auth requirements (API keys) or error behavior for unknown presets, but the provided behavioral context is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact (three sentences) and front-loaded with the core purpose in the first sentence. Each sentence earns its place: purpose, energy logic, data retention, and the explicit non-sending behavior. It loses the top score only because it crams several distinct facts (energy mapping, retention, non-sending) into a somewhat dense structure, but there's no waste or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters with 100% schema coverage, a nested object field, and no output schema, the description is appropriately complete. It adds the non-obvious details the schema can't convey: the energy→suffix mapping, the Zero Data Retention default, the overrides merge priority, and the crucial non-sending behavior. There is no output schema, but the description explicitly states what it returns (URL, headers, body), compensating well.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter, including the energy enum values with direct mapping to suffix behavior. The description adds context about energy mapping (floor/nitro/base) and overrides merging semantics ("merged in last") which aligns with and enriches the schema. The description reinforces rather than extends, which is appropriate given full coverage. Baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ("Build a ready-to-send OpenRouter chat-completion request body") with a clear resource (named preset + energy budget). It distinctly states what it does NOT do (sends the request), which is an excellent positive and negative definition. Despite no siblings being provided, the purpose is unambiguous and self-contained.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly narrates the energy-preset selection logic (low→:floor, high→:nitro, balanced→base slug), telling the agent when to use which energy value. It doesn't explicitly name alternatives or exclusions, since no sibling tools exist to differentiate against. The guidance is strong on the core decision, slightly lighter on external context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
routeLLM
TDQS
Scored across 1 tool
There is only one tool, so there is no possibility of ambiguity or overlap with other tools. The purpose of routeLLM is clearly defined and distinct.
With only a single tool, there is no pattern to evaluate for consistency. The name routeLLM uses a camelCase convention mixing a verb and a domain noun, which is readable though generic.
A single tool feels thin for a server named 'openrouter-router.' The router domain likely requires at least companion operations (e.g., send, list presets, get budget) to be practically useful on its own, so one tool is under-scoped.
The tool only builds a request body and explicitly does not send the request. For routing purposes, there is a notable dead end—no send capability, no way to list/manage presets, and no health or configuration operations. The surface is significantly incomplete for the stated routing purpose.
Maintenance
Related MCP Connectors
Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.
Cloudflare Workers MCP server: ai-model-router
Focused MCP server for OpenAI image/audio generation (v2.0.0). Wraps endpoints via HAPI CLI.
MCP server for AI dialogue using various LLM models via AceDataCloud
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA simple server that acts as a Master Control Program (MCP) for unified interaction with OpenAI and Anthropic (Claude) AI models through a single API endpoint.15MIT
- AlicenseAqualityBmaintenanceA Python MCP server that lets MCP hosts call OpenRouter models for chat, image generation, embeddings, and model search via FastMCP with .env support and retry handling.51MIT
- AlicenseAqualityDmaintenanceA lightweight MCP server that enables AI coding assistants to interact with OpenRouter API for direct queries, file analysis, and batch processing.3MIT
- FlicenseNot gradedqualityDmaintenanceLocal MCP server that exposes fixed tools for GPT, Claude, and Gemini while routing to any OpenAI-compatible chat completions backend with independent configuration per target.1-