delegate-mcp
Allows delegating file reading and long context tasks to a cheap model via OpenAI-compatible API, enabling expensive orchestrator models to get concise answers without consuming context on raw text.
Click on "Install 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., "@delegate-mcpanalyze the src folder for where authentication is handled"
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.
delegate-mcp
An MCP server that delegates reading — files or long context — to a cheap model, so your expensive orchestrator gets a tight answer instead of spending its own context window on raw text.
What it does
delegate-mcp exposes three Model Context Protocol tools —
analyze, query, and resume — that hand a reading task to a cheap, high-context
"reader" model behind an OpenAI-compatible API. Point analyze at a directory and it packs
the files, asks the reader your question, and returns a short structured answer. The
orchestrator never sees the raw files; it sees the conclusion.
Related MCP server: Middleman
Why
A capable orchestrator model is expensive per token. Reading is not the expensive part — reasoning is. When you make the orchestrator itself slurp a large directory or a long document into its context just to answer "where is X handled?" or "summarise this", you pay top-tier prices for bulk reading and you eat into context you'd rather keep for the actual task.
delegate-mcp splits the two: a cheap model does the bulk reading, the orchestrator keeps
its context for reasoning. A directory that would cost tens of thousands of tokens to load
comes back as a few hundred tokens of answer. You choose any OpenAI-compatible provider and
model, so you set the price/quality trade-off yourself.
Install & Quick start
Requires Node.js ≥ 20.
# 1. Write a config file (see Configuration) with at least one provider.
# 2. Run the server (stdio transport):
npx -y delegate-mcp --config ./config.jsonThe server speaks MCP over stdio — you normally don't run it by hand; you register it with an MCP client and the client launches it. Register it like any stdio MCP server:
{
"mcpServers": {
"delegate": {
"command": "npx",
"args": ["-y", "delegate-mcp", "--config", "/absolute/path/to/config.json"]
}
}
}(Works with any MCP-capable client — Claude Code, Claude Desktop, or your own host. Use an
absolute config path, since the client sets its own working directory.) Once connected,
the client lists three tools: analyze, query, resume.
On startup the server is fail-loud: a missing or invalid config, or a provider whose
api_key env var is unset, aborts the launch with a clear message on stderr and a non-zero
exit — it never serves in a half-configured state. stdout is reserved for the MCP
JSON-RPC stream; all diagnostics go to stderr.
Configuration
The config is a single JSON file. Its path is resolved from three sources, first found wins:
CLI flag —
--config <path>(also-c <path>or--config=<path>).Environment —
DELEGATE_MCP_CONFIG=<path>.Home convention — the first of these that exists:
$XDG_CONFIG_HOME/delegate-mcp/config.json(default~/.config/delegate-mcp/config.json)~/.delegate-mcp/config.json~/.delegate-mcp.json
If none is found, the server exits and prints every path it checked, in priority order.
A leading ~ in any path field is expanded to your home directory.
config.example.json
{
"providers": [
{
"name": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": "env:OPENAI_API_KEY",
"default_model": "gpt-4o-mini",
"weight": 1,
"timeout_ms": 60000,
"max_input_tokens": 128000,
"headers": {}
}
],
"disabled_providers": [],
"session_dir": "~/.delegate-mcp/state/sessions",
"metrics_file": "~/.delegate-mcp/state/metrics.jsonl",
"default_max_output_tokens": 4096,
"file_walker": {
"max_file_bytes": 262144,
"max_total_bytes": 4194304,
"exclude_glob": ["coverage", "*.min.js", "src/generated/**"]
}
}Secrets
An api_key should be a reference to an environment variable, written "env:VAR":
"api_key": "env:OPENAI_API_KEY"At load time this resolves to process.env.OPENAI_API_KEY. If that variable is unset, the
server fails loud — naming only the variable, never a value. A literal key is tolerated
but triggers a warning; secret values are never echoed in any log, warning, or error.
Disabling a provider
disabled_providers lists provider names to keep in the file but drop from the active
pool — handy for parking a provider without deleting its block:
"providers": [ { "name": "openai", ... }, { "name": "backup", ... } ],
"disabled_providers": ["backup"]A disabled provider is filtered out before validation, so an incomplete parked block never blocks startup. If every provider ends up disabled, startup fails.
Schema
Top level
Field | Type | Required | Default | Description |
| array | yes | — | Non-empty list of provider blocks (below). |
| string[] | no |
| Provider names to exclude from the active pool. |
| string | no |
| Directory for per-session JSON files. |
| string | no |
| Append-only JSONL metrics path. |
| number | no | — | Output-token cap used when a tool call omits |
| object | no | see below | File-packer caps and excludes for |
providers[]
Field | Type | Required | Default | Description |
| string | yes | — | Unique id; appears in result headers and metrics, and is referenced by |
| string | yes | — | OpenAI-compatible API base URL. |
| string | yes | — | Secret. Use |
| string | yes | — | Model used unless a session pins another (see |
| number | no |
| Relative weight in the weighted-random order; higher ⇒ tried first more often. |
| number | no |
| Per-request timeout in milliseconds. |
| number | no | — | Advisory per-provider input ceiling (informational in this release; packed-input size is bounded by |
| object<string,string> | no | — | Extra HTTP headers sent to the provider. |
file_walker
Field | Type | Required | Default | Description |
| number | no |
| Per-file cap; larger files are included truncated, with a marker. |
| number | no |
| Total corpus cap; once hit, remaining files are skipped ( |
| string[] | no |
| Extra excludes, merged on top of the always-on defaults (see File packer). |
Tools reference
Every tool returns a text result whose first line is a fixed header:
[delegate <tool>] provider=<name> model=<model> in=<input_tokens> out=<output_tokens> session=<id>followed by the reader's answer. Every call also appends one line to the metrics file
(success or failure). A failure — all providers down, unreadable work_dir, unknown session
— comes back as an MCP error result (isError), never as a crash.
analyze
Pack a directory (or a single file) and answer a prompt about it.
Argument | Type | Required | Description |
| string | yes | Absolute path to a directory or file to pack and read. |
| string | yes | What to extract / answer from the packed files. |
| integer | no | Output-token cap for this call (floored to 200). |
Returns the header + answer, plus (when files were skipped or truncated) a one-line
footer. The result header carries a session_id you can pass to resume.
// call
{ "work_dir": "/repo/src/auth", "prompt": "Where is the session token verified? Cite files." }[delegate analyze] provider=openai model=gpt-4o-mini in=1843 out=176 session=7f3e9c02-...
Token verification happens in `session.ts`:
- `verifyToken()` (session.ts:88) checks the signature and expiry.
- It is called by the `requireAuth` middleware (middleware.ts:22) on every request.
[delegate analyze] packed 12 file(s), 3 skippedquery
A fileless one-shot question to the reader model.
Argument | Type | Required | Description |
| string | yes | The question / instruction for the delegate model. |
| integer | no | Output-token cap for this call (floored to 200). |
Returns the header + answer, with a session_id for follow-ups.
// call
{ "prompt": "Summarise the tradeoffs of optimistic vs pessimistic locking in two bullets." }[delegate query] provider=openai model=gpt-4o-mini in=24 out=98 session=b1a4d7e8-...
- Optimistic: no locks held; cheap under low contention, but retries/aborts on conflict.
- Pessimistic: locks up front; predictable under high contention, but risks blocking/deadlock.resume
Continue a prior session with a new prompt, pinned to the same provider and model that served it. Continuity is reconstructed from the stored history.
Argument | Type | Required | Description |
| string | yes | The |
| string | yes | The follow-up prompt. |
| integer | no | Output-token cap for this call (floored to 200). |
Returns the header + answer. An unknown session — or one whose provider is no longer configured — is returned as an error result.
// call
{ "session_id": "b1a4d7e8-...", "prompt": "Now give a one-line rule of thumb for choosing." }[delegate resume] provider=openai model=gpt-4o-mini in=142 out=41 session=b1a4d7e8-...
Rule of thumb: optimistic when conflicts are rare, pessimistic when they're the norm.Agent usage
Delegate large reads to save tokens
You have a delegate-mcp MCP server with tools analyze, query, resume. It routes large-context reads to a cheap model so they don't fill your expensive context.
Default to delegating when you'd otherwise pull a large payload into context:
Scanning a large file / whole directory for a fact or summary →
analyze(work_dir + prompt)A big log / command output / web page you only need summarized → save to a temp dir and
analyzeit (or paste small inline data intoquery)A general question not needing your own reasoning →
queryA follow-up on a prior delegate answer →
resume(session_id + prompt), pinned to the same model
Rule of thumb: raw content likely > ~5K tokens and you only need to find/summarize (not edit) → delegate and reason over the reply.
Read directly instead when: (1) about to edit the file; (2) it's tiny (< ~50 lines); (3) you need an exact quote/line number/byte-precise detail; (4) the delegate failed → fall back and say so.
Prompting: state the output shape (table/bullets/JSON); cap max_output_tokens; trust the answer (don't re-read the source to "double-check" unless a destructive action depends on it).
How it works
MCP client (your orchestrator)
│ analyze / query / resume
▼
delegate-mcp
│
├─ files ····· pack work_dir → prompt (exclude · cap · skipped list)
├─ providers · weighted-random order → sequential failover
├─ sessions ·· one JSON per session (pin provider + model on resume)
└─ metrics ··· append one JSONL line per call (ok or error)
│
▼
cheap reader model (OpenAI-compatible) ──► tight answer + headerProvider pool
One client is built per provider at startup. On each call the pool computes a
weighted-random order (roulette selection without replacement, by weight, default 1),
then tries providers sequentially: any error — network, HTTP, malformed response — falls
through to the next provider. If all fail, the call returns an error result naming the last
failure. The number of failed attempts before the served one is recorded as failovers.
resume uses a single-provider view of the pool so it stays pinned to the session's provider.
File packer
analyze walks work_dir with a deterministic depth-first traversal (the same tree always
yields a byte-identical prompt) and serialises each file as a --- file: <path> --- block,
followed by an explicit skipped list so nothing is dropped invisibly. Controls:
Excludes —
.gitignore-style. A pattern without/(node_modules,*.min.js) matches a path segment at any depth; a pattern with/(src/generated/**) is anchored towork_dir. Yourexclude_globis merged on top of an always-on default floor —node_modules,.git,dist,build,target,.next,__pycache__,*.lock,.env*,*.pem,*.key,id_*,*secret*— that cannot be dropped, so common secret-bearing files never leave your machine even if you override the list.Binary skip — files with a NUL byte, or a high ratio of control bytes, in the first 4 KiB are skipped (UTF-8 text, including non-Latin scripts, is preserved).
Caps —
max_file_bytestruncates a large file (with a marker);max_total_bytesstops the corpus and marks the resttotal-cap-hit. Skip reasons areexcluded,binary,total-cap-hit,read-failed,stat-failed.
Sessions
Each analyze / query writes one JSON file to session_dir (<session_id>.json);
resume reads it back and appends the new turns. Persistence is full-overwrite with no
garbage collection — old session files accumulate, and pruning them is your
responsibility (they're plain files; clear the directory when you like). Session ids are
validated to contain no path separators (traversal-safe).
Metrics
Every call appends one JSON line to metrics_file. Recording never throws: an I/O
failure is swallowed (with a stderr warning) so a metrics problem can't take down the call
it describes. Each line carries:
{"ts":"2026-01-01T12:00:00.000Z","uuid":"...","tool":"analyze","provider":"openai","model":"gpt-4o-mini","input_tokens":1843,"output_tokens":176,"input_bytes":72104,"duration_ms":1320,"status":"ok","session_id":"7f3e...","files_attached":12,"failovers":0}An error line sets "status":"error", adds an "error" message, and reports provider /
model as -. The file is JSONL — tail it, or feed it to any log / metrics pipeline.
Security & privacy
File contents leave your machine.
analyzesends the packed files to whichever external provider you configured. Do not point it at directories containing secrets, credentials, or personal data you aren't willing to send to that provider. The always-on exclude floor (.env*,*.pem,*.key,id_*,*secret*, …) reduces accidental leaks but is not a substitute for choosingwork_dirdeliberately.Keep the config out of version control. It references secrets; store the file with tight permissions:
chmod 600 ~/.config/delegate-mcp/config.jsonPrefer
env:VARfor API keys so the secret lives in your environment, not the file. Secret values are never printed by this server.
Troubleshooting
no delegate-mcp config found— none of the three resolution sources located a file. The message lists every path checked; pass--config <absolute-path>or setDELEGATE_MCP_CONFIG.api_key references environment variable "X", but it is not set— export the variable in the environment the MCP client launches the server in (a client's env may differ from your interactive shell's).all N provider(s) failed; last error: …— every provider errored for that call. Checkbase_url, the model name, network, and quota; the last provider's error is quoted.Empty answer / truncated reasoning — some thinking models need output headroom. Raise
default_max_output_tokens(or passmax_output_tokenson the call); the floor is 200.A file you expected wasn't read — check the
skipped (…)tail in theanalyzeoutput for the reason (excluded,binary,total-cap-hit, …), and review yourexclude_globand caps.
Contributing
Issues and pull requests are welcome. Development:
npm ci
npm run lint # eslint
npm run build # tsup → dist/
npm test # vitest
npm run typecheck # tsc --noEmitPlease keep changes typed, tested, and provider-agnostic (the pool depends only on the OpenAI-compatible chat-completions surface).
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/art-ws/delegate-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server