ask-mcp
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., "@ask-mcpAsk me to choose between Postgres and MySQL for the new schema"
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.
ask-mcp
A blocking "ask the user" MCP tool that renders questions as real HTML forms in the browser — approvals, choices, tables, markdown, short forms — and returns structured, validated answers to the agent.
The problem
Agent harnesses ship basic question tools (opencode's built-in question, Claude Code's AskUserQuestion). They render as inline chips in the chat and cap out fast:
No room for context — a plan, a diff summary, or a comparison table has to be squeezed into chat text before the question.
Loose answers — free text the model must re-parse and hope it inferred your intent correctly, instead of validated structured data.
No audit trail — once the chat scrolls away, the question, the options you saw, and the answer you gave are gone.
No lifecycle — nothing to review later, no way to see or cancel what's currently pending.
Related MCP server: Homespun
The solution
ask gives every question a proper surface. The agent calls the MCP tool, a form opens in your browser, and the tool call blocks until you answer, cancel, or the timeout fires:
agent ── tools/call("ask", {...}) ──► ask-mcp ──► renders form + opens browser
│
agent ◄── structured result ──── submit/cancel/timeout ◄┘Control — decide with full context instead of a one-line prompt: option cards, callouts, step lists, tables, required rejection notes, forms with real typed fields and server-side validation.
Visibility — every interaction is inspectable: live pending asks you can cancel from an admin panel, a day-partitioned history of every spec and response, archived renders of exactly what you saw, and named templates that turn recurring decisions into reviewable assets.
Screenshots
Choice cards | Free-text escape hatch |
|
|
Plan approval with action bar | Info blocks |
|
|
Install & run
bunx @pylotlight/ask-mcp # run without installing
npx -y @pylotlight/ask-mcp # same, via npm
npm i -g @pylotlight/ask-mcp # or install globally → `ask-mcp`Requires Node ≥ 22 or Bun ≥ 1.2. There are two ways to connect it to your MCP client — pick one:
Option A: client-spawned (npx style)
The client launches the package itself, like any other npm MCP server. The tool call blocks, the form opens in your browser, and a small loopback HTTP server serves the form pages (falls back to a free port if 8787 is busy).
Claude Code:
claude mcp add ask -- npx -y @pylotlight/ask-mcp --stdioopencode — ~/.config/opencode/opencode.json:
{
"mcp": {
"ask": {
"type": "local",
"command": ["npx", "-y", "@pylotlight/ask-mcp", "--stdio"],
"enabled": true
}
},
"experimental": { "mcp_timeout": 600000 }
}Claude Desktop (stdio-only client) — claude_desktop_config.json:
{
"mcpServers": {
"ask": { "command": "npx", "args": ["-y", "@pylotlight/ask-mcp", "--stdio"] }
}
}mcp_timeout matters: clients default to ~30 s tool timeouts, which kills any blocking ask. Ten minutes is a good starting point; match it with --timeout-ms if you want the server and client to agree.
Option B: shared server
Run the server yourself and point clients at it — one instance shared by multiple clients, and the gateway to the admin panel, history, and the /api/ask HTTP twin:
bunx @pylotlight/ask-mcp # listens on http://127.0.0.1:8787, forms auto-openopencode: "type": "remote", "url": "http://127.0.0.1:8787/mcp" (plus mcp_timeout as above).
Claude Code: claude mcp add --transport http ask http://127.0.0.1:8787/mcp.
Other clients: anything speaking MCP Streamable HTTP can point at http://<host>:8787/mcp; stdio-only clients can bridge with supergateway/mcp-proxy.
If the port is busy (e.g. ask-mcp is already running), it says so instead of crashing.
Features
Five input kinds —
approve,single_choice,multi_choice,text,form. Thetypefield is optional and inferred from the fields you provide (multi_choiceis the one exception — set it explicitly).Other escape hatch — choice prompts accept
other: { placeholder }, rendering a final pseudo-option with a free-text field: typing auto-selects it, an empty Other blocks submit, and the answer arrives asotherText.Info blocks — headings, paragraphs, markdown (safe subset), callouts, steps, option cards, tables, dividers.
Blocking semantics — the MCP call stays open until the user responds; results come back as
structuredContentplus a human-readable summary.Templates — recurring asks saved as named, validated recipes (
deploy-confirm, your own); the agent discovers them withask_templatesand invokes by id.Admin panel — token-gated dashboard: live pending asks with cancel, full history browser, config editor, template CRUD.
Artifacts — every ask is persisted (
spec.json,response.json,render.html) under~/.config/ask-mcp/YYYY-MM-DD/<token>/, with optional retention pruning.Live pages — forms track status over SSE: submitted → delivered, cancelled, expired; the page locks and tries to dismiss itself when done.
HTTP twin —
POST /api/ask+GET /api/templatesgive scripts and CI the same pipeline as the MCP tool (see docs/commands.md).Safe by construction — HTML-escaped rendering, strict zod schemas, per-ask 128-bit capability tokens, strict CSP, loopback-by-default binding.
The ask tool
{
"title": "Deploy to production?", // required, ≤ 120 chars
"subtitle": "12 checks passed", // optional
"blocks": [ // context shown above the input
{ "type": "markdown", "markdown": "**3 files** changed (+142 −38)" },
{ "type": "option_card", "id": "now", "title": "Deploy now", "meta": "~4 min", "description": "Blue-green, instant rollback" },
{ "type": "option_card", "id": "later", "title": "Wait for Friday", "description": "Lower traffic window" }
],
"input": { // `type` optional — inferred
"options": [
{ "id": "now", "label": "Deploy now" },
{ "id": "later", "label": "Later" }
]
},
"options": { "density": "comfortable", "allowCancel": true } // optional
}Input inference
Fields present | Resolved type |
|
|
|
|
|
|
anything else (or nothing) |
|
Per-kind extras: approve accepts approveLabel, rejectLabel, noteRequired (never|on_reject|always), notePlaceholder; single_choice/multi_choice accept other: { placeholder } and multi_choice also min/max; text accepts placeholder, multiline, minLength, maxLength, submitLabel; form takes a JSON-schema-ish object (string/number/integer/boolean fields, enum, format, bounds, required). blocks is optional — a title-only approve ask is valid. multi_choice is never inferred: pass type: "multi_choice" explicitly.
Results
structuredContent depends on the interaction:
{ "action": "choose", "optionId": "now", "note": "optional" }
{ "action": "choose", "optionIds": ["a", "b"] }
{ "action": "choose", "optionId": "__other__", "otherText": "custom answer" }
{ "action": "submit", "value": "free text" }
{ "action": "submit", "values": { "field": "value", "count": 3, "ok": true } }
{ "action": "approve" | "reject" } // note included when provided
{ "action": "cancel" } // user cancelled (nothing was sent)
{ "action": "timeout" } // treat the question as unansweredThe content[0].text is a one-line summary (e.g. User chose "Deploy now".), so clients that surface text get a readable answer too. Submissions are re-validated server-side against the original ask before they're accepted.
Templates
Recurring interactions can be saved as named templates (~/.config/ask-mcp/templates/<id>.json, editable in the admin panel) and referenced by id — explicit fields override the template:
{ "template": "deploy-confirm", "title": "Deploy to staging?" }Use the ask_templates tool to list what's installed. See docs/commands.md.
Slash command (opencode / openchamber)
npx -y @pylotlight/ask-mcp install-commands # installs /ask-admin/ask-admin opens the admin panel (/admin) in the browser. All ask interactions are agent-driven via the MCP ask tool (and ask_templates for discovery); the /api/ask + /api/templates HTTP endpoints are the plain-HTTP twin for scripts. See docs/commands.md.
Admin panel
Start with --admin-token <t> (or --auth-token) and open /admin:
Live asks — pending queue with one-click cancel, streamed over SSE
History — the day-partitioned artifact trail (spec/response side by side, archived renders)
Config — a form over
~/.config/ask-mcp/config.json(CLI > env > file precedence; safe fields apply live)Templates — CRUD for ask recipes, validated with the same pipeline as live asks
Hidden (404) until a token is configured; see docs/admin.md.
CLI reference
ask-mcp [options]
ask-mcp install-commands [--dir <target>] [--force]
--port <n> HTTP port (default: 8787)
--host <addr> Bind address (default: 127.0.0.1)
--base-url <url> Public base URL for form links
--config <path> Config file (default: ~/.config/ask-mcp/config.json; CLI > env > file > defaults)
--data-dir <dir> Artifact directory (default: ~/.config/ask-mcp)
--retention-days <n> Prune artifacts older than n days at startup + every 6 h (default: 0 = forever)
--timeout-ms <n> Ask blocking timeout (default: 600000, min 1000)
--surface <mode> auto | apps | browser (MCP Apps is deferred; see docs/)
--auth-token <t> Require Bearer auth on the MCP endpoint
--admin-token <t> Unlock the /admin panel (falls back to --auth-token)
--no-open Don't auto-open forms in a browser
--stdio Serve MCP over stdin/stdout (client-spawned mode); form pages still served over loopback HTTP
-h, --help Show helpEvery flag has an ASK_MCP_* env equivalent; persistent settings live in the config file (managed in the admin panel's Config tab).
Authoring guidance for models
Put alternatives in
option_cardblocks and reference the same ids in choice options — cards become the clickable choices automatically (no duplication).approveis for a single recommended plan; a rejection reason flows throughnote(require it withnoteRequired).Use
form/textto collect data, choices to pick between plans.One primary input per ask; ask follow-ups in subsequent calls.
Keep blocks concise — this is a decision surface, not a report.
Security model
Binds to loopback by default; set
--host 0.0.0.0only with--auth-token.The MCP endpoint accepts optional Bearer auth (constant-time compare). Form pages rely on their unguessable 128-bit per-ask token as a capability URL — that's what makes browser auto-open work without headers.
Pages ship a strict CSP (
default-src 'none', no framing),no-referrer, and every string is escaped before rendering; markdown is sanitized by whitelist, never passed through.Form POSTs are re-validated against the ask's schema; cancel/submit are single-shot state transitions.
Development
git clone https://github.com/PylotLight/ask-mcp && cd ask-mcp
bun install
bun run build # tsc emit → dist/
bun run typecheck # tsc --noEmit
bun run test # vitest
bun src/index.ts # run from source (or: node dist/index.js)Source layout:
src/
index.ts entrypoint: config, stores, http server, signals (--stdio adds the stdio MCP transport)
config.ts CLI/env/config-file parsing + validation (--help has the full list)
commands/ install-commands (opencode/openchamber slash command installer)
schema/ zod: blocks, input spec (+ lenient inference), args, results
server/ http routes, mcp endpoint, admin panel routes, /api/ask, shared ask flow
store/ pending asks (in-memory, TTL/pruning), artifact persistence, templates
render/ page/styles/client script/blocks/markdown/escaping + admin dashboard UI
util/ tokens, open-in-browserArtifacts land in --data-dir (default ~/.config/ask-mcp) as YYYY-MM-DD/<token>/{spec.json,response.json,render.html} — a full audit trail of every question asked, shown, and answered.
Roadmap
The admin panel (live ask monitor, history, config, templates) and the /ask-admin slash command are implemented — see docs/admin.md and docs/commands.md. The broader exploration (re-asks, webhooks, richer interaction blocks) lives in docs/admin-roadmap.md. MCP Apps (rendering the ask inside the MCP client itself) is designed but intentionally deferred — see docs/surface-a-mcp-apps.md.
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.
Related MCP Connectors
An AI concierge that turns static forms into adaptive AI conversations. From any MCP client.
Poke your human for approvals and decisions during agent sessions — answered with one phone tap.
Interactive video forms that capture authentic responses. Build engaging forms in minutes.
Create and wire up contact forms from your coding agent. Forms, snippets, and submissions.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI clients to create multi-field forms, send approval requests via email, and retrieve structured human responses. It facilitates human-in-the-loop workflows by allowing agents to collect data and check form completion status.2,013MIT
- AlicenseAqualityAmaintenanceHand a human a rich interactive UI by URL from any MCP client and get structured data back — forms, approvals, surveys, pickers, editable lists. Round-trip human-in-the-loop for agents.2627MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to render native-looking floating dialogs and forms on the user's desktop, capturing user interactions like button clicks and form inputs.
- AlicenseBqualityDmaintenanceEnables AI agents to ask human operators questions through polished browser dialogs, supporting text/choice/confirmation inputs and file attachments.7MIT
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/PylotLight/ask-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server



