Skip to main content
Glama
nbhson

Universal Prompt Gate MCP Server

by nbhson

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-chosen

  • 4 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

rewrite_prompt

prompt (required), language?, context?, rewrite_level (light/balanced/detailed)

original_prompt, rewritten_prompt, changes_summary, warnings?

review_and_select_prompt

prompt (required), language?, context?; after pending_level_selection (text fallback): rewrite_level?; after pending_user_selection: selection?, rewritten_prompt?, feedback? (required for selection=update)

Approved: status=approved, selected_option (original/rewritten), selected_prompt, original_prompt, rewritten_prompt · Cancelled: status=cancelled, selected_option=cancel, selected_prompt=null · No-elicitation fallback: status=pending_level_selection (level menu; no rewrite yet) then status=pending_user_selection + both versions + 4 choices (original/rewritten/update/cancel; update + feedback rewrites again and returns a NEW pending_user_selection)

get_client_capabilities

—

elicitation_supported, structured_elicitation_supported, transport, integration_mode, mandatory_gating_enforceable

Key principles:

  • rewrite_prompt never claims the rewritten prompt is approved — it only produces a candidate rewrite.

  • review_and_select_prompt is 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 inspector

Configuration (environment variables)

Create a .env file (see .env.example) or export the variables directly:

Variable

Default

Description

PROMPT_GATE_LLM_BASE_URL

http://127.0.0.1:8080/v1

LLM endpoint (OpenAI-compatible)

PROMPT_GATE_LLM_MODEL

qwen3.5-9b (example — verify against your llama.cpp version)

Model name

PROMPT_GATE_LLM_API_KEY

local-dev-key

API key (for local dev, no real key needed)

PROMPT_GATE_TIMEOUT_MS

180000

LLM timeout in ms (thinking models on CPU need more time)

PROMPT_GATE_LLM_RETRY_MAX

3

Retry count for network errors (idempotent calls only)

PROMPT_GATE_LLM_MAX_TOKENS

2048

Max completion tokens (thinking models need a larger budget)

PROMPT_GATE_LLM_ENABLE_THINKING

(unset)

true/false — enable/disable reasoning (qwen3 / llama.cpp thinking models)

PROMPT_GATE_LLM_EXTRA_JSON

(unset)

JSON object merged into the LLM request body (e.g. {"chat_format":"chatml"})

PROMPT_GATE_ECHO_FALLBACK

true

When the client does not support MCP elicitation, the gate tool returns pending_level_selection / pending_user_selection text menus instead of a hard error (agent re-calls with rewrite_level / selection / feedback)

PROMPT_GATE_TRANSPORT

stdio

stdio or http

PROMPT_GATE_EXTERNAL_LLM

(unset)

Optional: cloud LLM endpoint

PROMPT_GATE_REWRITE_POLICY_FILE

(unset)

Custom meta-prompt policy file (presets: news/code/research, …) — overrides the default strategy

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); in rewrite_prompt (no picker) the agent chooses it directly.

  • Global default (env): PROMPT_GATE_REWRITE_POLICY_FILE — the meta-prompt preset

rewrite_level decides the enrichment depth for that call; PROMPT_GATE_REWRITE_POLICY_FILE selects the meta-prompt used as the system prompt. qwen3.5-9b is 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:

    1. 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 criteria

      The agent asks the user which level to use and re-calls the tool with the SAME inputs plus rewrite_level set to the user's choice. The agent must never pick for the user.

    2. 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 gate

      The agent asks the user, then re-calls with selection set to "original" / "rewritten" / "cancel" (and, for rewritten, the rewritten_prompt text the user saw).

    3. Update loop (optional). If the user picks "update", the agent re-calls with selection: "update" plus feedback containing the requested changes (and rewritten_prompt of the version they reviewed). The tool rewrites again and returns a NEW pending_user_selection (with revision_count bumped) to review. Repeat until the user picks original, rewritten, or cancel.

    4. 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/models

The 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 start

Integrate 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 defaults

Option 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.servers with an environment field, and command is 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.

Variable

Default

Meaning

PROMPT_GATE_PROVIDER

openai-compatible

openai-compatible / openai / custom

PROMPT_GATE_CUSTOM_PROVIDER_MODULE

(unset)

Path to a custom provider module (only used when provider=custom)

PROMPT_GATE_LLM_BASE_URL

http://127.0.0.1:8080/v1

OpenAI-compatible endpoint

PROMPT_GATE_EXTERNAL_LLM

(unset)

Override the base URL (cloud endpoint)

PROMPT_GATE_LLM_MODEL

qwen3.5-9b

Model name

PROMPT_GATE_LLM_MAX_TOKENS

2048

Max completion tokens

PROMPT_GATE_TIMEOUT_MS

180000

Timeout in ms

PROMPT_GATE_LLM_ENABLE_THINKING

(unset)

true/false — disable reasoning (qwen3 / llama.cpp)

PROMPT_GATE_LLM_EXTRA_JSON

(unset)

JSON object merged into the LLM request body

PROMPT_GATE_ENV_FILE

(unset)

Explicit path to a .env file

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. &quot;thông tin việt nam&quot;"])

  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 &amp; 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"| ASTOP

Diagram 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 exposed

  • No 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:coverage

Test 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 selection

  • Capability 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.ts

Troubleshooting

Symptom

Cause

Fix

LLM request timed out

llama.cpp is slow, the model is too large, or a thinking model on CPU

Increase PROMPT_GATE_TIMEOUT_MS (e.g. 300000) and PROMPT_GATE_LLM_MAX_TOKENS (e.g. 4096)

LLM HTTP 401

Wrong API key

Check that PROMPT_GATE_LLM_API_KEY matches your llama.cpp key

LLM returned an empty completion

The model produced no text (high temperature, small max_tokens)

Lower temperature, increase PROMPT_GATE_LLM_MAX_TOKENS (default 2048, raise if needed)

LLM returned empty content but produced reasoning_content

A thinking model (qwen3/3.5) is not respecting thinking:false

Use a non-thinking model (e.g. qwen2.5-7b), or upgrade llama.cpp to a build that supports thinking:false, or set PROMPT_GATE_LLM_MAX_TOKENS=4096+ so the model has enough budget

Client reports elicitation_unsupported

The client does not support elicitation

Text fallback runs by default: expect pending_level_selection / pending_user_selection menus and relay the user's choices (rewrite_level / selection / feedback for the update loop). In strict mode (PROMPT_GATE_ECHO_FALLBACK=false) only use the gate when elicitation_supported: true

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

node build/index.js does not run

Not built yet

Run npm run build first

License

Apache-2.0

Available Tools

3 tools
get_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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 short context (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 selection set to "original", "rewritten", or "cancel" matching the user's choice.

  • Choose rewrite_level to fit the task: light for quick one-shot answers, balanced (default) for most coding/research work, detailed when the user explicitly wants a fully-specified spec.

  • Pass language only 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesThe original prompt to review. This is the user's latest message only.
contextYes1-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.
languageNoOutput 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.
selectionNoONLY 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_levelNoHow much enrichment to apply. "light" = minimal; "balanced" (default) = add missing structure/context/criteria; "detailed" = full spec with acceptance criteria.
rewritten_promptNoONLY 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

A4.3/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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_level to fit the task: light for quick one-shot answers, balanced (default) for most coding/research work, detailed when the user explicitly wants a fully-specified spec.

  • Pass language only 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesThe original prompt to rewrite. This is the user's latest message only.
contextYes1-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.
languageNoOutput 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_levelNoHow 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

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 3 tool updatesv0.1.2
    • First observedget_client_capabilities
    • First observedreview_and_select_prompt
    • First observedrewrite_prompt

TDQS

A4.2/5.0

Scored across 3 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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.
    16
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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 PyPI
    3
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables 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
    -