Universal Prompt Gate MCP Server
Allows the MCP server to use OpenAI as a cloud LLM provider for rewriting and enriching prompts, providing an alternative to local llama.cpp or custom endpoints.
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., "@Universal Prompt Gate MCP Serverreview and rewrite this prompt: thông tin việt nam"
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.
Universal Prompt Gate MCP Server
A standalone MCP server that works with many coding agents. It lets users review and select a prompt before it is sent to an LLM. It rewrites prompts using a local LLM, has the user pick the enrichment level first, displays 4 choices (original / rewritten / update / cancel — "update" requests changes and loops), and keeps the flow safe and flexible for agents.
Core use case
You type a short prompt in an agent:
"thông tin việt nam"First, the user picks the enrichment level (light / balanced / detailed). The MCP server then rewrites (enriches) it with a local LLM (llama.cpp) into:
"Summarize the latest news about Vietnam today, categorized by economy, politics, society, and technology. Prioritize reliable sources."
Before the prompt is forwarded to the large LLM, the user is shown 4 choices:
[1] Use original prompt ("thông tin việt nam")
[2] Use rewritten prompt (the enriched version above)
[3] Update (enter feedback → the prompt is rewritten again; loops)
[4] Cancel (do not call the LLM)The user picks one; the chosen prompt (or a "cancelled" state) is then sent to the large LLM. If they pick update, they describe what to change and the prompt is rewritten again — the menu keeps looping until they choose original, rewritten, or cancel. This is the core flow of the server.
Related MCP server: Hivelore
Key features
Prompt review & rewrite before sending: every prompt passes through a "gate"; nothing is forwarded automatically
User picks the enrichment level:
light/balanced/detailed— interactive picker, never agent-chosen4 user choices: (1) use the original, (2) use the rewritten, (3) update — request changes and review another rewrite (loops), (4) cancel
Rewrite = context enrichment: adds missing context, output structure, and quality criteria — no new intent, avoiding drift
Local LLM rewrite (llama.cpp, OpenAI-compatible) — prompts never leave your machine
Works with many coding agents: Claude Code, Cursor, Cline, Continue, OpenCode, …
2 integration modes:
Standard MCP mode — the agent calls the tool; the MCP server handles the elicitation UI
Mandatory Gating (when the agent supports hooks) — the prompt is not forwarded until the user confirms
Multi-provider LLM: local llama.cpp, OpenAI (cloud), custom endpoint
Safety: no full-prompt logging, no shell execution from prompts, secrets redacted in logs, timeout & cancellation, no placeholder credentials
MCP tools
Tool | Main input | Main output |
|
|
|
|
| Approved: |
| — |
|
Key principles:
rewrite_promptnever claims the rewritten prompt is approved — it only produces a candidate rewrite.
review_and_select_promptis the "gate" tool — it returns an approved prompt only after the user explicitly chooses.Cancel ≠ approved: when the user cancels, the response is a distinct protocol outcome (
status=cancelled) and never exposes an approved prompt.No silent fallback: on LLM error, the original is not auto-selected. A clear error is returned.
No auto-select on timeout: the user must choose manually; nothing is auto-selected by default.
Full schema & behavior: docs/ARCHITECTURE.md.
Installation
Requires Node.js 20+.
# 1. Clone & install
cd tool-prompt-rewrite-mcp
npm install
# 2. Build
npm run build
# 3. Run with MCP Inspector (try the tools)
npm run inspectorConfiguration (environment variables)
Create a .env file (see .env.example) or export the variables directly:
Variable | Default | Description |
|
| LLM endpoint (OpenAI-compatible) |
|
| Model name |
|
| API key (for local dev, no real key needed) |
|
| LLM timeout in ms (thinking models on CPU need more time) |
|
| Retry count for network errors (idempotent calls only) |
|
| Max completion tokens (thinking models need a larger budget) |
| (unset) |
|
| (unset) | JSON object merged into the LLM request body (e.g. |
|
| When the client does not support MCP elicitation, the gate tool returns |
|
|
|
| (unset) | Optional: cloud LLM endpoint |
| (unset) | Custom meta-prompt policy file (presets: |
Two separate axes:
Per-call:
rewrite_level—light/balanced/detailed. In the gate tool (review_and_select_prompt) it is chosen by the user via the picker (the agent must not decide it); inrewrite_prompt(no picker) the agent chooses it directly.Global default (env):
PROMPT_GATE_REWRITE_POLICY_FILE— the meta-prompt preset
rewrite_leveldecides the enrichment depth for that call;PROMPT_GATE_REWRITE_POLICY_FILEselects the meta-prompt used as the system prompt.qwen3.5-9bis an example — verify the model name against your llama.cpp version.
When the client does not support elicitation (text fallback)
Some agents (older VS Code, Cline, Continue, …) do not declare the MCP
elicitation capability. When that happens, the gate tool
review_and_select_prompt cannot show an interactive picker. The server has
two behaviors, controlled by PROMPT_GATE_ECHO_FALLBACK:
true(default) — echo fallback: the flow runs over plain-text menus instead, as up to 4+ calls:Level menu. The first call returns
status: "pending_level_selection"(the prompt has not been rewritten yet — no LLM call) with the three numbered levels:[1] light — minimal changes; keep close to the original [2] balanced — add missing structure, context, and quality criteria [3] detailed — full spec with acceptance criteriaThe agent asks the user which level to use and re-calls the tool with the SAME inputs plus
rewrite_levelset to the user's choice. The agent must never pick for the user.Selection menu. The tool now rewrites the prompt and returns
status: "pending_user_selection"with both versions in plain text and the numbered choices:[1] original — use the user's exact text [2] rewritten — use the LLM-enriched version [3] update — request changes: describe what to adjust, then the prompt is rewritten again [4] cancel — use neither; abort the prompt gateThe agent asks the user, then re-calls with
selectionset to"original"/"rewritten"/"cancel"(and, forrewritten, therewritten_prompttext the user saw).Update loop (optional). If the user picks
"update", the agent re-calls withselection: "update"plusfeedbackcontaining the requested changes (andrewritten_promptof the version they reviewed). The tool rewrites again and returns a NEWpending_user_selection(withrevision_countbumped) to review. Repeat until the user picks original, rewritten, or cancel.Final call. Returns the normal approved/cancelled outcome. This call does not invoke the LLM again.
false— strict: the tool returns a hard compatibility error, as in the original design. Use this when you want to refuse to gate at all unless the client supports elicitation.
The echo fallback is not a silent fallback: it never auto-selects, never forwards the prompt without an explicit user choice (level and version), and cancellation still exposes no approved prompt.
Run a local LLM (llama.cpp)
# Download a model (one time)
./llama-server -m qwen3.5-9b -c 8192 --port 8080 --api-key local-dev-key
# Verify
curl http://127.0.0.1:8080/v1/modelsThe MCP server calls this endpoint to rewrite prompts. No internet required.
Run the MCP server
# Default (stdio) — for desktop agents
node build/index.js
# Or via package.json
npm startIntegrate with agents
Standard MCP mode is the default and works with every MCP-capable agent. Mandatory Gating (hooks) is an extension — optional, and only possible when the agent exposes a hook API.
Example MCP server configuration
Add the server to your agent's config (common JSON shape):
{
"mcpServers": {
"prompt-gate": {
"command": "node",
"args": ["/absolute/path/to/tool-prompt-rewrite-mcp/build/index.js"]
}
}
}Or, when installed from npm:
{
"mcpServers": {
"prompt-gate": {
"command": "npx",
"args": ["-y", "universal-prompt-gate-mcp"]
}
}
}Each agent has a different configuration mechanism — see the compatibility matrix.
Passing configuration (env) to the server — 3 ways
The server reads config with this precedence (higher wins):
1. Real environment variables (passed by the MCP client via `env`/`environment` in its JSON config)
2. A `.env` file (auto-loaded: PROMPT_GATE_ENV_FILE → CWD → next to build/index.js)
3. Built-in defaultsOption A — env in JSON (recommended when publishing)
Claude Code / Cursor / VS Code Copilot use the mcpServers (or servers) key plus an env field:
{
"mcpServers": {
"prompt-gate": {
"command": "node",
"args": ["/absolute/path/to/build/index.js"],
"env": {
"PROMPT_GATE_LLM_BASE_URL": "http://127.0.0.1:8080/v1",
"PROMPT_GATE_LLM_MODEL": "qwen3.5-9b",
"PROMPT_GATE_LLM_MAX_TOKENS": "4096",
"PROMPT_GATE_TIMEOUT_MS": "300000",
"PROMPT_GATE_LLM_ENABLE_THINKING": "false"
}
}
}
}OpenCode V2 uses
mcp.serverswith anenvironmentfield, andcommandis an array:{ "mcp": { "servers": { "prompt-gate": { "type": "local", "command": ["node", "/absolute/path/to/build/index.js"], "environment": { "PROMPT_GATE_LLM_MODEL": "qwen3.5-9b" }, }, }, }, }
Option B — a .env file (local dev)
Copy .env.example → .env at the repo root. The server loads it automatically at startup (no env needed in JSON). When a client spawns the server from a different CWD, the server looks for .env next to build/index.js (the repo). Set PROMPT_GATE_ENV_FILE=/path/to/.env to point to a specific file.
Option C — custom provider (ship your own, used when publishing)
"env": {
"PROMPT_GATE_PROVIDER": "custom",
"PROMPT_GATE_CUSTOM_PROVIDER_MODULE": "/absolute/path/to/my-provider.js"
}my-provider.js must export:
export function createCustomLLMProvider(cfg) {
// cfg: LLMConfig (baseUrl, model, apiKey, timeoutMs, retryMax, maxTokens, …)
return {
isConfigured: () => true,
chat: async (messages, options) => {
// call your endpoint/model/API, return a STRING (the completion).
// throw on error — the server maps it to a GateError.
return await callYourApi(messages, options);
},
};
}→ Ship this provider as a separate package (e.g. @me/my-llm-provider) and point PROMPT_GATE_CUSTOM_PROVIDER_MODULE at the installed file (require.resolve / absolute path). No need to edit the prompt-gate package source.
Provider-related env variables
Variable | Default | Meaning |
|
|
|
| (unset) | Path to a custom provider module (only used when provider=custom) |
|
| OpenAI-compatible endpoint |
| (unset) | Override the base URL (cloud endpoint) |
|
| Model name |
|
| Max completion tokens |
|
| Timeout in ms |
| (unset) |
|
| (unset) | JSON object merged into the LLM request body |
| (unset) | Explicit path to a |
Which tool to use when
rewrite_prompt— when you just want to see an enriched version, without a user gate (e.g. preview).review_and_select_prompt— when you need a real "gate": the user must choose before the prompt is used. This is the primary tool of the "Universal Prompt Gate".get_client_capabilities— to check whether the connected client supports elicitation, before calling the gate tool.
How it works
Workflow diagram (Mermaid)
flowchart TD
U(["👤 User<br/>types a prompt<br/>e.g. "thông tin việt nam""])
subgraph AGENT["🤖 Coding Agent (MCP client)"]
A1["Calls tool<br/><b>review_and_select_prompt</b>"]
A3["Receives JSON result"]
A4{"Use the result?"}
AOK["Send <b>selected_prompt</b><br/>to the large LLM"]
ASTOP["Stop / report cancelled"]
end
subgraph MCP["🛡️ Universal Prompt Gate MCP Server"]
T["Tool: <b>review_and_select_prompt</b>"]
V["Validate input (Zod)"]
LP["User picks rewrite LEVEL<br/>light / balanced / detailed<br/>(mandatory, before rewrite)"]
R["Call LLM to rewrite at that level"]
RM{"LLM ok?"}
RE["Return error<br/>(<b>no</b> silent fallback)"]
E["Show ORIGINAL & REWRITTEN<br/>via elicitation"]
CHOICE{"User picks one of four"}
O1["Use original"]
O2["Use rewritten"]
O4["Update — request changes<br/>(feedback; rewrites again)"]
O3["Cancel"]
end
subgraph LLM["🧠 Local LLM (llama.cpp)"]
L1["/v1/chat/completions"]
end
U -->|"1. submit prompt"| A1
A1 -->|"2. MCP tool call"| T
T --> V
V -->|"valid"| LP
LP -->|"3. elicitation — user must choose"| R
R -->|"4. fetch"| L1
L1 -->|"5. completion"| R
R --> RM
RM -->|failure| RE
RM -->|success| E
E -->|"6. elicitation"| CHOICE
CHOICE -->|"7a"| O1
CHOICE -->|"7b"| O2
CHOICE -->|"7d"| O4
CHOICE -->|"7c"| O3
O4 -->|"8d. apply feedback → rewrite again (loop)"| R
O1 -->|"8a. approved"| A3
O2 -->|"8b. approved"| A3
O3 -->|"8c. cancelled"| A3
RE -->|error| A3
A3 --> A4
A4 -->|"approved"| AOK
A4 -->|"cancelled / error"| ASTOPDiagram source:
docs/WORKFLOW.md.
Standard MCP Mode
1. Agent submits a prompt ("thông tin việt nam")
2. Agent calls the MCP tool → user picks the enrichment level (light/balanced/detailed)
3. LLM (llama.cpp) rewrites the prompt at that level
4. MCP server returns the original & the rewritten version (via the elicitation UI)
5. MCP server shows the 4 choices (1/2/3/4)
6. User picks one (1/2/3/4) — "update" (3) lets them enter requested changes and the prompt is rewritten again (loop back to step 3)
7. MCP server returns the chosen prompt (or the "cancelled" state)
8. Agent sends that prompt (or stops if cancelled)Mandatory Gating (when the agent supports hooks)
An agent hook intercepts the prompt → calls review_and_select_prompt → inside the MCP server:
User picks the level (light / balanced / detailed)
→ Rewrite the prompt at that level (llama.cpp)
→ Show the choices (original / rewritten / update / cancel; "update" loops with user feedback)
→ User selects & confirms
→ Return the result (or cancel)The prompt is not forwarded when the user picks "Cancel".
Cancellation Flow
User picks Cancel → MCP Server confirms the cancellation → The prompt is not forwarded to the agent/LLM
Response: { status: "cancelled", selected_option: "cancel", selected_prompt: null }Cancel is a distinct protocol outcome — the response does not expose
selected_prompt. There is no silent fallback to the original on LLM errors.
Safety & security
Input length limits, output validation (Zod)
Timeout & cancellation (explicit, no auto-select)
Injection detection; the prompt is treated as untrusted data
Session management (pending requests), isolation per session/request ID, cleanup of abandoned requests
No silent fallback: on LLM error, the original is not auto-selected — a clear error is returned
No auto-select on timeout: the user must choose manually
Cancel = distinct outcome: response
status=cancelled, no approved prompt exposedNo full-prompt logging; secrets redacted in logs; no placeholder credentials
No auto-forward on cancel; no shell execution from prompts
Testing
# Run unit + integration tests (mocked LLM, no llama.cpp required)
npm test
# Watch mode
npm run test:watch
# Coverage
npm run test:coverageTest coverage includes:
Rewrite (success, timeout, malformed, language/context pass-through)
Review/select: user-chosen level picker (before the rewrite), original, rewritten, update+feedback revision loop (both elicitation and text fallback), cancel, cancellation via action, LLM error (no fallback), elicitation unsupported + text fallback flow (
pending_level_selection→pending_user_selection→ approval), invalid selectionCapability detection (conservative default, no name-based inference)
Concurrent sessions (isolation)
Logger (redaction, stderr-only)
Config (env defaults, overrides, clamping)
Development & build
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run format # prettier
npm run build # tsc
npm run dev # tsx (no build)Project structure
tool-prompt-rewrite-mcp/
├── package.json
├── tsconfig.json
├── tsconfig.test.json
├── eslint.config.js
├── .prettierrc
├── .env.example
├── .gitignore
├── README.md
├── docs/
│ ├── ARCHITECTURE.md
│ ├── AGENT_INTEGRATION.md
│ ├── WORKFLOW.md
│ └── Universal Prompt Gate MCP Architecture.png
├── src/
│ ├── index.ts # entry (stdio)
│ ├── config.ts # load env → typed config
│ ├── logger.ts # safe logger (stderr, redaction)
│ ├── types.ts # shared domain types
│ ├── elicitation.ts # MCP elicitation wrapper
│ ├── capability/
│ │ └── capability.ts # client capability detection
│ ├── session/
│ │ └── session.ts # pending-request management
│ ├── llm/
│ │ ├── index.ts # provider factory
│ │ └── provider.ts # OpenAI-compatible provider + retry
│ ├── rewrite/
│ │ └── rewrite.ts # meta-prompts + RewriteService
│ └── tools/
│ ├── index.ts # tool registration
│ ├── rewritePrompt.ts # rewrite_prompt tool
│ ├── reviewAndSelect.ts # review_and_select_prompt tool (the gate)
│ └── getClientCapabilities.ts
└── test/
├── rewrite.test.ts
├── review.test.ts
├── cancellation.test.ts
├── concurrent.test.ts
├── capability.test.ts
├── config.test.ts
├── logger.test.ts
└── fixtures/
└── llm-mocks.tsRelated documentation
docs/ARCHITECTURE.md— overall architecture, compatibility matrix, env variables, securityMCP Inspector — test & debug the server
llama.cpp — run a local OpenAI-compatible API
Troubleshooting
Symptom | Cause | Fix |
| llama.cpp is slow, the model is too large, or a thinking model on CPU | Increase |
| Wrong API key | Check that |
| The model produced no text (high temperature, small max_tokens) | Lower |
| A thinking model (qwen3/3.5) is not respecting | Use a non-thinking model (e.g. |
Client reports | The client does not support elicitation | Text fallback runs by default: expect |
Prompt does not go through the gate when using an agent | The agent has no hooks (standard mode) | This is a limit of standard MCP — see Mandatory Gating |
| Not built yet | Run |
License
Available Tools
3 toolsget_client_capabilitiesClient CapabilitiesA
Reports which interaction features are available for the current MCP client/session: elicitation support, structured elicitation, transport, integration mode, and whether a mandatory prompt gate is enforceable. Capabilities are derived from verified protocol negotiation, not from the agent name.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers the key trait: capabilities come from 'verified protocol negotiation, not from the agent name,' which tells the agent the report is authoritative rather than heuristic. It does not state what happens on failed negotiation or that the call is side-effect free, keeping it short of a 5.
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 first front-loads the purpose and the enumerated outputs, the second adds the sourcing caveat. The list of features is informative rather than padded, and nothing could be cut without losing meaning.
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?
With no output schema, the description compensates well by enumerating the reported capability fields, and a zero-param read tool needs nothing more on inputs. It stops short of describing failure modes or the shape of each reported value (e.g., transport enumeration), which would make it fully self-contained.
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?
The tool takes zero parameters, so the baseline is 4; there is no parameter semantics to clarify. The description correctly focuses on the response fields instead of inventing input details.
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 ('Reports') and resource ('which interaction features are available for the current MCP client/session'), then enumerates the exact features reported: elicitation, structured elicitation, transport, integration mode, and prompt-gate enforceability. This is unmistakably distinct from the prompt-oriented siblings rewrite_prompt and review_and_select_prompt.
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 is implied rather than stated: an agent can infer it should check this before relying on elicitation or enforcing a prompt gate, but there is no explicit 'use this when/when not' guidance and no mention of alternatives. The clause about derivation 'not from the agent name' hints at a precondition but does not frame a decision rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_and_select_promptPrompt Gate (user-confirmed)A
Generates a rewritten version of the prompt, then asks the user to choose: use original, use rewritten, or cancel. Returns only the approved prompt. Cancellation is a distinct outcome and never exposes an approved prompt.
If the client does not support MCP elicitation, the tool returns a distinct "pending_user_selection" result: it shows both versions in plain text with the three numbered choices and asks the agent to re-call this tool with selection set to the user's choice ("original" / "rewritten" / "cancel"). Never auto-select.
CALLING GUIDE (for the LLM):
FIRST call (rewrite): pass prompt + context; do NOT pass
selection. ALWAYS pass a shortcontext(1-3 sentences) summarizing the conversation so far.If the first call returns status "pending_user_selection": show the two versions to the user, ask which to use, then call again with the SAME inputs PLUS
selectionset to "original", "rewritten", or "cancel" matching the user's choice.Choose
rewrite_levelto fit the task:lightfor quick one-shot answers,balanced(default) for most coding/research work,detailedwhen the user explicitly wants a fully-specified spec.Pass
languageonly when the user wants the rewritten prompt in a language different from the original. Do NOT switch the language on your own judgment — the server auto-detects the prompt language and preserves it by default.
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | The original prompt to review. This is the user's latest message only. | |
| context | Yes | 1-3 sentences summarizing the conversation/session so far (what the user has asked, what files/topics are in play, what was decided). STRONGLY RECOMMENDED: pass this on every call so the rewrite is grounded in prior context. Omit only for brand-new sessions with no history. | |
| language | No | Output language, e.g. "english" or "vietnamese". ONLY pass this when the user explicitly asks for a different output language. If the user has not asked, omit it — the server auto-detects the prompt's language and preserves it. Do NOT pass "english" just to "improve clarity"; that switches the output language and is a drift. | |
| selection | No | ONLY for the SECOND call of a pending_user_selection flow: the user's explicit choice after the server could not show an interactive picker. On the first call (rewrite) this must be omitted. Values: "original", "rewritten", "cancel". Never auto-select; pass it only after the user has chosen. | |
| rewrite_level | No | How much enrichment to apply. "light" = minimal; "balanced" (default) = add missing structure/context/criteria; "detailed" = full spec with acceptance criteria. | |
| rewritten_prompt | No | ONLY for the SECOND call of a pending_user_selection flow: the exact rewritten text the user saw in the first call's "pending_user_selection" result. Omit on the first call. When present with selection="rewritten", this is what gets approved — so the user approves exactly what they read, not a re-rewrite. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses the elicitation fallback, the `pending_user_selection` result shape, that cancellation is a distinct outcome that never yields an approved prompt, and that the server auto-detects and preserves language. These are exactly the behavioral traits an agent needs before calling.
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?
Front-loaded with the core purpose and outcome, then organized under a clear CALLING GUIDE heading. It is longer than typical but nearly every line carries routing or sequencing information; only mild repetition between the prose and the parameter notes.
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?
There is no output schema, so the description must describe returns — and it does: the approved prompt, the distinct `pending_user_selection` payload, and the cancellation outcome. For a six-parameter, two-phase tool with no annotations, nothing essential 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 coverage is 100%, so the baseline is 3, but the description adds calling-order semantics not obvious from the schema: which parameters belong to the first call versus the second, and the practical guidance that `light` suits one-shot answers while `detailed` is for full specs. This meaningfully extends the field descriptions.
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 two-step action (generate a rewritten prompt, then obtain user selection) and a precise scope: 'Returns only the approved prompt.' It distinguishes itself from a plain rewrite by making user confirmation the core behavior, though it never names the sibling `rewrite_prompt` to contrast against.
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 CALLING GUIDE is unusually explicit about the first vs. second call, when to pass `selection`, when to omit it, and 'Never auto-select.' It also gives clear when-to-use rules for `rewrite_level` and `language`. The one gap is that it never routes the agent between this tool and the sibling `rewrite_prompt`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rewrite_promptPrompt Rewrite (no approval)A
Re-emit the given prompt with richer context, structure, and quality criteria. This tool only produces a candidate rewrite; it does NOT approve the result. Use review_and_select_prompt for the gated, user-confirmed flow.
CALLING GUIDE (for the LLM):
ALWAYS pass a short
context(1-3 sentences) summarizing the conversation/session so far so the enrichment is grounded. Do not omit it.Choose
rewrite_levelto fit the task:lightfor quick one-shot answers,balanced(default) for most coding/research work,detailedwhen the user explicitly wants a fully-specified spec.Pass
languageonly when the user wants the rewritten prompt in a language different from the original. Do NOT switch the language on your own judgment — the server auto-detects the prompt language and preserves it by default.
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | The original prompt to rewrite. This is the user's latest message only. | |
| context | Yes | 1-3 sentences summarizing the conversation/session so far (what the user has asked, what files/topics are in play, what was decided). STRONGLY RECOMMENDED: pass this on every call so the rewrite is grounded in prior context. Omit only for brand-new sessions with no history. | |
| language | No | Output language, e.g. "english" or "vietnamese". ONLY pass this when the user explicitly asks for a different output language. If the user has not asked, omit it — the server auto-detects the prompt's language and preserves it. Do NOT pass "english" just to "improve clarity"; that switches the output language and is a drift. | |
| rewrite_level | No | How much enrichment to apply. "light" = minimal (keep close to original); "balanced" (default) = add missing structure/context/criteria; "detailed" = full spec with acceptance criteria. Pick based on task complexity. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose key behavior: it only produces a candidate rewrite and does NOT approve the result. It also warns about the language-drift risk and server-side auto-detection. It stops short of describing output shape or side effects in detail, but the mutation-vs-read semantics are clear.
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?
Front-loads the core purpose and the key exclusion in the first two sentences, then uses a compact bulleted calling guide. Every sentence earns its place; no filler.
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 generation tool with no output schema and no annotations, the description covers purpose, the non-approval behavior, and per-parameter usage. It doesn't describe the return payload, but the 'candidate rewrite' framing makes the outcome clear enough.
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 coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: it maps rewrite_level values to task types (light/balanced/detailed), states context is grounded session history, and gives a strong warning about language drift. This goes beyond restating the schema descriptions.
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+resource ('Re-emit the given prompt with richer context, structure, and quality criteria') and explicitly distinguishes itself from the sibling by naming review_and_select_prompt for the gated flow. The title reinforces the 'no approval' scope, so an agent can tell the two prompt tools apart immediately.
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 CALLING GUIDE gives explicit when/when-not guidance: always pass context, choose rewrite_level by task type, and only pass language when the user asks. It also names the alternative tool and the condition that selects it ('gated, user-confirmed flow'), leaving nothing 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.
3 tool updates
v0.1.2- First observed
get_client_capabilities - First observed
review_and_select_prompt - First observed
rewrite_prompt
TDQS
Scored across 3 tools
get_client_capabilities is clearly distinct as a capability probe. rewrite_prompt and review_and_select_prompt overlap in that both generate rewritten prompts, but the descriptions explicitly draw the line: rewrite_prompt produces an unapproved candidate while review_and_select_prompt runs the gated, user-confirmed flow. The boundary is documented, so misselection is unlikely but not impossible.
All names use snake_case with verb-first phrasing (get_*, rewrite_*, review_and_select_*), which is readable and mostly uniform. review_and_select_prompt is a compound verb phrase rather than a simple verb_noun, a minor deviation from the otherwise consistent pattern.
Three tools is a lean surface but each maps to a distinct stage of the workflow: capability discovery, candidate rewrite, and gated approval/selection. The count is slightly thin but well-scoped and nothing feels redundant or padded.
The lifecycle for a prompt-gate server is largely covered: negotiate capabilities, generate a rewrite, and handle user approval including a documented fallback for clients without elicitation. Minor gaps exist around configuration or non-elicitation batch handling, but core agent workflows are supported without dead ends.
Maintenance
Related MCP Connectors
Preventive human-approval write-gate for AI agents: writes commit only after a human approves.
Security gateway for AI agents: policy, approval, and audited execution, no secrets shared.
Pre-execution governance for AI agents. Deterministic PASS/FAIL/REVIEW verdicts, replayable proof.
Human-in-the-loop for AI coding agents — ask questions, get approvals via Slack.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI coding assistants like Cursor and Claude to engage in real-time two-way dialogue, allowing them to pause for clarification and request user confirmation before executing tasks. It features a modern UI for managing interaction prompts, predefined options, and project analysis to reduce errors and API costs.16MIT
- AlicenseAqualityAmaintenanceEnforces team knowledge and workflow policies for AI coding agents by providing context, decisions, and gates before code changes are made.164Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables local, cross-provider preflight validation of LLM integration changes—model, prompt, structured-output, and provider-call modifications—with no-spend checks, evidence on speed, tokens, and cost, and explicit human approval before paid runs.1,023 PyPI3MIT
- FlicenseNot gradedqualityBmaintenanceEnables autonomous agents and multi-agent frameworks to route actions through deterministic human approval gates before execution. Enforces risk tiers, reversible checkpoints, and token approval bounds so that risky or costly operations can be reviewed, bounded, and rolled back without LLM round-trips.7-