@lobstack/mcp
OfficialAn MCP server for the Lobstack API: preview routing and costs without a key, and with a key, run model chats and read spend.
Preview which model Lobstack's router would use for a prompt, the complexity score, tier, and estimated cost — no API key required.
List gateway models with tier, provider, context window, and USD per-million input/output token prices; null means unpriced, not free.
Send a prompt or conversation through the gateway and get the reply plus a receipt: served model, usage, cost, savings reason, quota, and dropped parameters.
Read organization spend over 7d/14d/30d/90d grouped by day, model, key, or agent, with request counts, tokens, errors, latency percentiles, and lower-bound warnings.
Use in Claude Desktop, Claude Code, Cursor, Zed, or any MCP stdio client, configured via
LOBSTACK_API_KEYand optionalLOBSTACK_BASE_URL.
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., "@@lobstack/mcppreview routing and cost for: summarise this changelog into three bullets"
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.
@lobstack-ai/mcp
An MCP server for the Lobstack API. One API key reaches models from five providers, and every call comes back with a receipt: which model served it, how many tokens, what it cost.
Works in Claude Desktop, Claude Code, Cursor, Zed, or anything else that speaks the Model Context Protocol over stdio.
Try it without a key
lobstack_route_preview is unauthenticated. Install the server with no
credential at all and an agent can still ask "which model would this prompt go
to, and what would it cost":
npx -y @lobstack-ai/mcpAdd it to your client using one of the blocks below, leave env out, and ask:
Preview how Lobstack would route: "summarise this changelog into three bullets"
The other three tools need a key, minted in Console → API keys.
Related MCP server: proxyllm-mcp
Install
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json on macOS,
%APPDATA%\Claude\claude_desktop_config.json on Windows:
{
"mcpServers": {
"lobstack": {
"command": "npx",
"args": ["-y", "@lobstack-ai/mcp"],
"env": {
"LOBSTACK_API_KEY": "lsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Restart Claude Desktop. The four lobstack_* tools appear under the tools menu.
Cursor
~/.cursor/mcp.json for every project, or .cursor/mcp.json for one:
{
"mcpServers": {
"lobstack": {
"command": "npx",
"args": ["-y", "@lobstack-ai/mcp"],
"env": {
"LOBSTACK_API_KEY": "lsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Claude Code
claude mcp add lobstack --env LOBSTACK_API_KEY=lsk_live_... -- npx -y @lobstack-ai/mcpZed
In settings.json, under context_servers:
{
"context_servers": {
"lobstack": {
"source": "custom",
"command": "npx",
"args": ["-y", "@lobstack-ai/mcp"],
"env": {
"LOBSTACK_API_KEY": "lsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}Tools
lobstack_route_preview
Scores a prompt against the same router the paid path uses and reports the model that would serve it, the capability tier, the complexity score, and the estimated cost. Runs no inference and spends nothing. Needs no API key.
argument | type | notes |
| string, required | Scored, never sent to a model. Max 8000 characters. |
| string | A model to compare against. Defaults to |
| string | Plan id, which sets the ceiling the router may reach. |
| integer | Defaults to half the prompt. |
| integer | Messages already in the conversation. |
Token counts are estimates — roughly four characters per token. The billed figure always comes from the provider's own usage block on the real request, and the tool says so in every answer.
A baseline is returned only when you named a model and the router moved away
from it. On auto it is null: there is no model you asked for to compare
against.
lobstack_models
The catalogue: model key, label, tier, provider, context window, and USD per
million input and output tokens. Optional tier and provider filters.
The first entry is auto — Nex 1, the router. It carries tier: "router"
and a null price on purpose: its cost is whichever model it picks, which is not
knowable until the request is scored. That is the one null in this list that is
not a gap.
Every other null price is. A model the registry cannot price comes back with
null and renders as —, and it is not free — a zero there would be a claim
that a real charge did not happen.
The full catalogue with rates is also public, no key required, at https://www.lobstack.ai/models.
lobstack_chat
Sends a prompt or a conversation and returns the reply plus the receipt.
argument | type | notes |
| string | A single user message. Use this or |
| array |
|
| string | Defaults to |
| string | Prepended to the conversation. |
| integer | Cap on the reply. |
| number | Some models do not accept it; the receipt says when it was dropped. |
The reply and the receipt come back as two separate content blocks, so whatever consumes the answer does not get a price line concatenated onto it. The structured result carries:
{
"text": "...",
"model": { "requested": "claude-opus-5", "served": "claude-haiku-4-5", "routed": true },
"usage": { "prompt_tokens": 400, "completion_tokens": 140, "total_tokens": 540 },
"receipt": {
"request_id": "req_...",
"cost_usd": 0.0011,
"cost_display": "$0.001100",
"priced": true,
"savings": {
"amount_usd": 0.0044,
"label": "saved",
"named": true,
"baseline_model": "claude-opus-5",
"baseline_reason": "named"
}
},
"quota": { "meter": "spend", "remaining_usd": 16.75 },
"dropped_params": []
}lobstack_spend
What the organization has spent over month (the UTC calendar month to date,
the Console's default window), 7d, 14d, 30d or 90d, grouped by day,
model, key or agent, with request counts, tokens, errors and latency
percentiles. Requires a key holding the usage:read scope. The default range
is 7d.
The total is the Console's figure. /api/v1/usage returns two totals from
two tables: spend.cost_usd, from the billing ledger that the allowance and
invoices are read from and that the Console's Spend shows, and
summary.cost_usd, the request trace's own copy of each price, kept for older
callers. They are written separately and can disagree. This tool reports
spend.cost_usd (and each group's ledger_cost_usd) as cost_usd, with
cost_source: "ledger". Only when the ledger figure is null or missing does it
fall back to summary.cost_usd, set cost_source: "trace", and say so in the
output.
It also sets is_floor. Unpriced rows sum as zero — the only arithmetic
available — so a total that includes one is a lower bound, not a total, and
this tool says how many there were, counted in the same table as the total.
Routing savings are two figures, never one. When the API sends savings,
the tool shows named (saved on models you asked for, measured) and
plan_ceiling (what auto requests would have cost on the best model your
plan allows: a comparison, not a saving) on separate lines. It never adds them
together, and it never computes a saving client-side from a copy of the rate
card.
Two rules about the numbers
A null cost is not zero. cost_usd: null means the API could not price
the call. It renders as unpriced, never as $0.00. Rendering it as $0.00
writes off a real charge, and that exact substitution ran for three months in
production.
baseline_reason decides what a saving may be called.
named— you asked for a model and got something cheaper. Like-for-like, and the only case labelledsaved.plan_ceiling— you sentauto, so the comparison is against the most expensive model your plan allows. Real, and not something you asked for: labelledvs ceiling, with the baseline model named next to it.missing — treated as unnamed. A receipt that does not say where its baseline came from does not get the flattering reading.
Configuration
variable | default | notes |
| none | Read once at startup. Never logged, never in a tool result. |
|
| The Lobstack API base URL. Change it only to point at a staging deployment. |
Use www, not the bare apex. lobstack.ai redirects to www.lobstack.ai,
and RFC 9110 §15.4
requires a client to drop Authorization across a host change — so the API
answers a perfectly good key with "missing credentials". This server rewrites
the apex and tells you it did, and refuses to follow any other 3xx rather than
send a request whose credential has been stripped.
The key
LOBSTACK_API_KEY is read from this process's environment and from nowhere
else. No tool takes a key, a token, or a base URL as an argument: a base URL
that can arrive as a tool argument is a credential that can be redirected by
whoever wrote the argument. Error text is scrubbed on the way out, including
text that came back from upstream.
This process holds a live credential for as long as your MCP client runs. The dependency list is the MCP SDK, zod, and what those two bring with them.
Development
npm install
npm run build
npm testThe tests run a real MCP client against the server over an in-memory transport,
and the server against a fake gateway over real HTTP. The fake gateway writes
its SSE stream in two pieces with the cut landing mid-frame, serves a model with
no price, and refuses any request to /route-preview that arrives carrying an
Authorization header — so a client that leaks a credential to a public
endpoint fails a test rather than shipping.
Licence
MIT
Available Tools
4 toolslobstack_chatChat through the gatewayA
Send a prompt or conversation through the Lobstack Gateway and get the reply plus a receipt: the model that actually served it, token counts, USD cost, and any saving with the reason it may be claimed. Model "auto" (the default) lets the router pick the cheapest model that can handle the prompt. This call spends money against the configured key's allowance.
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | Lobstack model key, e.g. "claude-sonnet-5". Defaults to "auto", which lets Token Intelligence pick the cheapest model that can handle the prompt. lobstack_models lists the keys. | |
| prompt | No | A single user message. Use this or `messages`, not both. | |
| system | No | System prompt, prepended to the conversation. | |
| messages | No | A full conversation, OpenAI-shaped. Use this or `prompt`, not both. | |
| max_tokens | No | Cap on the reply length. | |
| temperature | No | Sampling temperature. Some served models do not accept it; the receipt says when it was dropped. |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | The assistant's reply. |
| model | Yes | |
| quota | Yes | Allowance remaining, as the gateway reported it. |
| usage | Yes | |
| receipt | Yes | Null when the endpoint sent no receipt at all. |
| dropped_params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose openWorldHint, non-readonly, non-idempotent, non-destructive. The description earns credit beyond that by stating it charges the configured key, that the receipt reports the actually-served model and any saving/claim reason, and that temperature may be silently dropped for some models.
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?
Three sentences with no wasted words, and the core action plus the cost consequence are front-loaded. Slightly dense but each sentence carries distinct information.
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?
For a chat/completion call with an output schema, the agent has the action, the money-spend warning, the routing behavior, and receipt contents. The main omission is explicit guidance to preview with lobstack_route_preview before spending.
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 model, prompt, system, messages, max_tokens and temperature are all already documented in the schema. The description restates the auto default but adds no syntax or format detail beyond what the schema carries; baseline 3 applies.
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?
Names a specific verb (Send) plus resource (prompt/conversation) and adds the scope of the return (reply + receipt with model, tokens, cost, savings). The function is unmistakable, but the description never names a sibling like lobstack_route_preview to sharpen the boundary, so it stops short of a 5.
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?
It flags a real usage consideration (this call spends money) and explains the auto default, but gives no explicit when/when-not guidance and does not route the agent to lobstack_route_preview for a cost-free preview. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lobstack_modelsList gateway modelsARead-onlyIdempotent
The models the Lobstack Gateway serves, with capability tier, provider, context window and USD price per million input and output tokens. A model the registry cannot price shows a null price, not zero.
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | Only models in this capability tier. Token Intelligence walks these from cheapest upward. | |
| provider | No | Only models from this provider, e.g. "anthropic", "openai", "google". |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| models | Yes | |
| unpriced_count | Yes | Models the registry could not price. Their prices are null, not zero. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds a genuinely useful behavioral detail beyond that: an unpriceable model yields a null price rather than zero, which prevents an agent from misreading the data. It stops short of describing pagination or ordering of the results.
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?
Two sentences, both load-bearing: the first states the resource and its fields up front, the second anticipates a likely misreading of the output. No filler or restatement of the title.
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?
An output schema exists, so return-format explanation is not required, and the description already sketches the payload. With both parameters fully described in the schema and annotations covering behavior, the definition is complete enough to invoke correctly; only filtering workflow guidance is absent.
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 both the tier enum and provider filter are fully documented in the schema, making 3 the baseline. The description mentions tier and provider only as returned fields, not as filter semantics, so it adds nothing beyond the schema for parameter meaning.
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 names the resource ('the models the Lobstack Gateway serves') and enumerates the returned fields (capability tier, provider, context window, USD price), so an agent knows exactly what this tool produces. It is unambiguous, though it never explicitly names a verb like 'list' and does not differentiate itself from siblings such as lobstack_route_preview.
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?
There is no statement of when to call this versus the siblings (lobstack_route_preview, lobstack_chat, lobstack_spend), nor any prerequisite or sequencing advice. The only contextual hint is embedded in the tier parameter schema ('Token Intelligence walks these from cheapest upward'), which is not usage guidance for the tool itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lobstack_route_previewPreview routing and costARead-onlyIdempotent
Score a prompt and report which model the Lobstack router would serve it with, and what that would cost. Runs no inference, spends nothing, and NEEDS NO API KEY — use it to pick a model before calling lobstack_chat, or to show what the gateway does on a machine with no key configured. Token counts are estimates; the billed figure comes from the provider's usage block on the real call.
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | The prompt to score. Scored, never sent to a model. | |
| plan_tier | No | Plan id, which sets the ceiling the router may reach. Defaults to the pro ceiling. | |
| requested_model | No | A model key to compare against, e.g. "claude-opus-5". Defaults to "auto". | |
| conversation_length | No | Messages already in the conversation; it feeds the complexity score. | |
| expected_output_tokens | No | How long the reply is expected to be. Defaults to half the prompt, which is the common chat ratio. |
Output Schema
| Name | Required | Description |
|---|---|---|
| tier | Yes | |
| reason | Yes | |
| routed | Yes | True when the router would serve something other than what was requested. |
| baseline | Yes | Only present when a model was named and the router moved away from it — the "named" case. |
| provider | Yes | |
| estimated | Yes | Always true. These are estimates, not a bill. |
| complexity | Yes | |
| served_label | Yes | |
| served_model | Yes | The model this prompt would actually be routed to. |
| token_estimate | Yes | |
| requested_model | Yes | |
| estimated_cost_usd | Yes | Null when the registry cannot price the model. |
| estimated_cost_display | Yes | |
| managed_key_configured | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description goes well beyond them by disclosing that it runs no inference, spends nothing, and requires no API key. It also flags that token counts are estimates and that the authoritative billed figure comes from the provider's usage block on the real call, which is exactly the caveat an agent needs.
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?
Three sentences, zero filler, with the cost/safety guarantee and the keyless property front-loaded before the usage routing. Every sentence earns its place.
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?
An output schema exists, so return values need no explanation, and the description still covers the safety profile, key requirement, cost semantics, and estimate-vs-billed distinction. Nothing an agent needs in order to call this correctly is missing.
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%, and each parameter already carries its own explanation including defaults for plan_tier and requested_model. The description adds only the estimate caveat around token accounting, so the baseline of 3 is appropriate.
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?
States a specific verb and resource ('Score a prompt and report which model the Lobstack router would serve it with') plus the second output dimension, cost. It explicitly contrasts with the sibling that actually performs inference, lobstack_chat, so an agent can route between them without opening either schema.
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?
Gives two concrete selection conditions: pick a model before calling lobstack_chat, and demonstrate gateway behavior on a keyless machine. It names the alternative explicitly and the circumstance that picks it, so no inference about when to invoke this tool is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lobstack_spendRead spend and usageARead-onlyIdempotent
What this organization has spent through the gateway over a range, broken down by day, model, key or agent, with request counts, tokens, error counts and latency percentiles. Requires an API key with the usage:read scope. Reports how many requests could not be priced, because a total that includes them is a floor.
| Name | Required | Description | Default |
|---|---|---|---|
| range | No | How far back to look. Defaults to 7d. | |
| group_by | No | How to break the total down. Defaults to model. |
Output Schema
| Name | Required | Description |
|---|---|---|
| range | Yes | |
| groups | Yes | |
| enabled | Yes | False when request tracing is not enabled on this deployment. |
| message | Yes | |
| summary | Yes | |
| group_by | Yes | |
| is_floor | Yes | True when some rows were unpriced or the row cap bound, so the totals are a lower bound, not a total. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the description is not obligated to restate that. It adds genuinely useful disclosure beyond the annotations: the usage:read scope requirement and the caveat that unpriced requests make any total a floor. It stops short of noting rate limits or freshness/caching behavior.
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?
Two sentences with no filler; the core capability is front-loaded and the auth requirement and pricing caveat follow in priority order. The first sentence is long and clause-dense, but every clause carries information an agent would otherwise have to infer.
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?
An output schema exists, so return values need not be explained, and the bounded range enum removes pagination concerns. The description covers scope, auth, and the pricing-floor caveat, but omits any hint of the consuming context (e.g. budget monitoring vs. cost attribution) that would complete the picture.
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% and both parameters are enum-constrained with documented defaults, so the schema already carries the parameter meaning. The description's 'over a range' and 'broken down by day, model, key or agent' mirror the enums without adding format or default detail beyond them, which is the baseline-3 case.
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 states a specific verb and resource ('what this organization has spent through the gateway over a range') and enumerates the exact breakdown dimensions (day, model, key, agent) plus the metrics returned. No sibling (route_preview, models, chat) does spend reporting, so an agent can route to this tool without ambiguity.
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?
Usage context is implied by the spend-reporting framing, and a concrete prerequisite is given ('Requires an API key with the usage:read scope'). However, there is no explicit when-to-use/when-not guidance and no alternatives are named, so routing between this and other tools is left to inference.
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.
4 tool updates
v0.1.0- First observed
lobstack_chat - First observed
lobstack_models - First observed
lobstack_route_preview - First observed
lobstack_spend
TDQS
Scored across 4 tools
Each tool targets a clearly distinct concern: route_preview scores/routes without spending, models lists the catalog, chat performs the actual paid call, and spend reports usage. The overlap risk between route_preview and chat is explicitly resolved by descriptions clarifying one runs no inference while the other spends money.
All tools share a consistent 'lobstack_' prefix and are snake_case, so they scan as one family. Suffix styles vary though — route_preview is verb_noun while models, chat and spend are bare nouns/verbs — a minor inconsistency but still readable and predictable.
Four tools is on the lean side but each earns its place and maps to a real workflow stage (discover, preview, execute, audit). Slightly thin, though appropriate for a focused gateway server.
The surface covers the core lifecycle: model discovery, routing/cost preview, the paid completion call, and spend auditing. Minor gaps exist (e.g. no embeddings, streaming controls, or key/scope management), but agents can accomplish the primary gateway tasks without dead ends.
Maintenance
Related MCP Connectors
Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.
Connect MCP clients to 2,000+ AI models without managing provider API keys.
Paid remote MCP for LLM security scans, jailbreak checks, analytics, checkout, and readiness.
- 0bridgeOAuthdev.0bridge
Every service you connect, one MCP endpoint for all your AI tools. Sign in once.
Related MCP Servers
- AlicenseAqualityAmaintenanceCentralized encrypted gateway that routes requests to 11+ LLM providers (API keys and CLI subscriptions) through a single OpenAI-compatible endpoint, with MCP tools for vault operations, code search, and shared state.309 npm2MIT
- AlicenseAqualityFmaintenanceMCP server for ProxyLLM, the OpenAI-compatible LLM gateway, enabling live model catalogs, plan-savings calculations, routing key management, and autonomous account signup.976 npmMIT
- AlicenseAqualityBmaintenanceEnables any AI agent to connect to any OpenAI-compatible LLM provider through a unified MCP interface, with automatic failover, caching, cost tracking, and multi-model consensus.13MIT
- FlicenseNot gradedqualityCmaintenanceProvides a stateless MCP gateway that lets AI agents execute Python in an isolated AST sandbox, run guarded read-only SQL queries, and automatically route tasks to cheaper or more capable models.-