mcp-feature-test
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
mcp-feature-test
An MCP server for checking which user-interaction features an MCP client (Claude Desktop, Claude Code, VS Code, Cursor, Open WebUI, the MCP Inspector, or your own client) actually supports:
Elicitation, form mode: the client shows a native dialog built from a JSON schema.
Elicitation, URL mode: the client opens a web page in the browser (the pattern for OAuth or secret entry).
Multi-step elicitation: a three-dialog wizard that carries signed
requestStatebetween rounds.How both elicitation modes flow between user, client, browser and server, on both protocol generations, is drawn step by step in docs/elicitation.md.
MCP Apps: an interactive HTML UI (
ui://resource) that the host renders in a sandboxed iframe.Progress, logging and cancellation for long-running tools.
Files: returning files in tool results (embedded resources,
resource_link, image, audio), uploading from an MCP App, app downloads, form fields the spec doesn't have, and the experimentalx-mcp-filedraft.Capability inspection: the server logs what each client declares and can report it back (
inspect_client,list_seen_clients).
The server speaks both protocol generations, 2026-07-28 (stateless, input_required) and 2025-era (initialize handshake, server→client elicitation/create), over stdio and Streamable HTTP. It is built on the MCP TypeScript SDK v2 (@modelcontextprotocol/server 2.4) and @modelcontextprotocol/ext-apps 2.0.
MCP App (Dialog Lab), light | MCP App (Dialog Lab), dark |
|
|
Colour picker ( | Values, light | Palettes, dark |
|
|
|
These screenshots come from the automated browser test (npm run screenshots). They show the apps inside a minimal test host, not inside a particular MCP client. Each client draws its own frame around the iframe. The colour picker also fits narrow hosts (360 px).
Contents
More documentation: elicitation: form vs. URL mode (diagrams) · MCP server vs. MCP App · architecture · testing · Docker · Open WebUI
Related MCP server: Everything MCP Server
Tools and the features they test
Tool | MCP feature exercised | Spec version that introduced it |
| Reports the protocol version, client info and declared capabilities (elicitation form/url, MCP Apps UI, sampling, roots, tasks, extensions) | n/a (reads |
| Every distinct client this server process has seen, with capability flags and request counts | n/a |
| Form elicitation: a yes/no confirmation dialog; accept, decline and cancel are each reported | Form elicitation: 2025-06-18 |
| Form elicitation with every allowed field type: string with min/max length, | Base types: 2025-06-18. Titled/multi-select enums and defaults on all types: 2025-11-25 |
| Two independent elicitations in a single round | Multiple |
| Three chained dialogs. Step 2 depends on step 1, and progress travels in HMAC-signed |
|
| URL-mode elicitation: the client opens a local page, the user enters a fake token, and the server confirms it received the token (masked) | URL mode: 2025-11-25. As an |
| URL mode in the 2025-11-25 push style: | 2025-11-25 only |
| Progress notifications, log messages, and cancellation ( | Progress and cancellation: 2024-11-05. Logging notifications are deprecated in 2026-07-28 |
| MCP App: tool | MCP Apps extension |
| App-only tool ( | MCP Apps |
| App-only tool behind the Dialog Lab's File upload card: takes a base64 file, returns its size and SHA-256, stores nothing. Size cap | MCP Apps (app → server |
| Returns what was submitted in the Dialog Lab, with the sketch as an image | n/a |
| One tool result with every way to hand over a file: embedded text resource (CSV), embedded blob resources (PNG, PDF), a |
|
Resource template | The sample files behind | Resource templates: 2024-11-05 |
| Form elicitation with schema features outside the spec, one dialog per probe: a | Not in any spec version (deliberately) |
| Experimental, not in the spec: a | Draft extension, not a SEP |
| MCP App used like a question: a colour picker ( | MCP Apps extension |
| Returns the colour the user picked as hex, | n/a |
| MCP App with WebGL: an interactive three.js viewer ( | MCP Apps extension (app → server |
| Returns the part the user selected in a | n/a |
Resource | A small glTF binary ( | Resources: 2024-11-05 |
Prompt | A prompt that walks the assistant through every tool above | Prompts |
Nothing these tools do has side effects: "delete" and "order" are only pretend, the tokens entered on the URL page are kept in memory and shown masked, and uploaded files are hashed and discarded (their contents are never logged).
Quick start
Requires Node.js 20 or newer.
npm install
npm run build # tsc + bundles the MCP App into dist/ui/dialog-lab.html
npm run inspector # optional: try it in the MCP InspectorThen connect a client (below) and ask the assistant to "call inspect_client", or use the try_all_dialogs prompt.
Running
Mode | Command | Endpoint |
stdio (what desktop clients launch) |
| stdin/stdout. URL-flow pages are served on |
Streamable HTTP |
|
|
Docker | see docs/docker.md |
HTTP mode serves both protocol generations on one endpoint. 2026-07-28 requests are handled statelessly. 2025-era clients get a classic session (Mcp-Session-Id). See docs/architecture.md.
Environment variables
Variable | Default | Mode | Meaning |
|
| HTTP | Listen port. |
|
| HTTP | Bind address. Use |
|
| HTTP | Externally visible base URL, without |
| (unset) | HTTP | Comma-separated hostnames accepted in the |
|
| stdio | Port for the URL-elicitation pages. Falls back to a free port (with a warning) if it is busy. |
|
| stdio | Bind address of that listener. Use |
|
| stdio | Base URL that the URL-elicitation links point to, when the browser has to use a different address or port. |
|
| both | How long |
|
| both | Largest decoded file |
|
| both |
|
|
| both |
|
All logs go to stderr. In stdio mode, stdout carries the protocol and never contains log output.
Connecting clients
Replace /abs/path/to/mcp-feature-test with your checkout. The configuration formats below are the ones these clients document. This repository does not test them automatically (see Client support).
Claude Desktop
claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"feature-test": {
"command": "node",
"args": ["/abs/path/to/mcp-feature-test/dist/stdio.js"]
}
}
}Restart Claude Desktop afterwards. Claude Desktop's config file only launches stdio servers. Remote HTTP servers are added as connectors in the app, and those generally need a publicly reachable HTTPS URL rather than localhost.
Claude Code
# stdio
claude mcp add feature-test -- node /abs/path/to/mcp-feature-test/dist/stdio.js
# or HTTP (start `npm run start:http` first)
claude mcp add --transport http feature-test http://127.0.0.1:3457/mcpRun /mcp inside Claude Code to check the connection.
VS Code (GitHub Copilot agent mode)
.vscode/mcp.json in a workspace, or the user-level mcp.json (MCP: Open User Configuration):
{
"servers": {
"feature-test": {
"type": "stdio",
"command": "node",
"args": ["/abs/path/to/mcp-feature-test/dist/stdio.js"]
},
"feature-test-http": {
"type": "http",
"url": "http://127.0.0.1:3457/mcp"
}
}
}Cursor
~/.cursor/mcp.json (global) or .cursor/mcp.json (project):
{
"mcpServers": {
"feature-test": { "command": "node", "args": ["/abs/path/to/mcp-feature-test/dist/stdio.js"] },
"feature-test-http": { "url": "http://127.0.0.1:3457/mcp" }
}
}MCP Inspector
npm run inspector # stdio
npx @modelcontextprotocol/inspector # then choose "Streamable HTTP", URL http://127.0.0.1:3457/mcpOpen WebUI
See docs/openwebui.md.
Docker
A ready-made image is published to ghcr.io/linuxrrze/mcp-feature-test. Every code change is released automatically as a new version (latest, X.Y.Z, X.Y, X and dated rollback tags; see docs/docker.md):
docker run --rm -p 127.0.0.1:3457:3457 ghcr.io/linuxrrze/mcp-feature-testSee docs/docker.md.
Any other HTTP client
Point it at http://127.0.0.1:3457/mcp (Streamable HTTP). A 2026-07-28 client sends its client info and capabilities in every request's _meta. A 2025-era client starts with initialize and then sends Mcp-Session-Id on every request. A browser-based client running on another host has to be allowed in ALLOWED_HOSTS. To check the endpoint quickly:
curl -s http://127.0.0.1:3457/ # "mcp-feature-test is running."What you should see
Tool | In a client with full support | If the client lacks the feature |
| A capability table (elicitation form/url, MCP Apps UI and its mimeTypes, sampling, roots, tasks) followed by the raw JSON | Always works |
| A dialog "Really delete …?" with one checkbox. The result says ACCEPTED, DECLINED or CANCELLED | Tool error: "… did not declare form-mode elicitation support …" |
| One form containing about 13 fields of every type, with defaults pre-filled. The result lists each value and its JSON type, which shows whether the client sends integers as numbers, arrays for multi-selects, and so on | Same tool error |
| Two dialogs ("what should I call you?" and "how are you?"), shown together or one after the other | Same tool error |
| Three dialogs in a row. The step 2 limit depends on the size chosen in step 1, and step 3 shows a summary | Same tool error |
| The client offers to open a URL. The page (below) asks for any token. Submit it, go back, accept, and the result reports a masked token | Tool error mentioning |
| 2025-era connections only: the same flow, and the client should close its dialog by itself when it receives | On 2026-07-28: a tool error explaining that push-style elicitation does not exist there |
| A progress indicator counting up. Cancelling stops it early | Result text: "Client did not request progress." |
| The Dialog Lab UI (screenshots above) | Only the text result, which says that no UI appeared because the client does not render MCP Apps |
| The last submissions as JSON, plus the sketch as an image | |
Dialog Lab File upload | Pick a file, press Upload to server: the app shows size and SHA-256 (and whether they match the local file). Try 100 KB, 1 MB and 10 MB files to find the host's message-size limit | An error under the upload card: the host's or the server's limit, or no |
Dialog Lab downloads | Three buttons: JSON (embedded text), sketch PNG (embedded blob) and linked PDF ( | All three are disabled, with a note, when the host doesn't advertise |
| Seven blocks: the list, a CSV, a PNG, a PDF, a link to a Markdown file, an image and a short beep | Whatever is missing from the list was dropped (or handed only to the model) |
| One dialog per probe. The result says per probe what came back; every one of these is outside the spec, so a fallback text box, a dropped field or a refusal is all legitimate | A client that refuses a schema ends the whole call with an error (the official TypeScript SDK client refuses everything except |
| Only clients implementing the draft files extension render a file picker; others show the raw object | A model can still call it with inline base64 |
| A colour picker panel (screenshots at the top) with the question, OK and Cancel. After OK the assistant learns the colour from the model context and/or a chat message ("I picked #xxxxxx for: …", | Only the text result; |
| A 3D view (screenshots below) you can drag, zoom and click. Selecting a part reports Server: stored, model context and (after Tell the assistant) the chat message; | Only the text result ("If no 3D view appeared, this client does not render MCP Apps."). With |
3D viewer ( | 3D viewer ( |
|
|

pick_color in Open WebUI 0.13.2. Open WebUI asks for two confirmations per answer: one for the app's tool call and one for its chat message. Dragging, image sampling through the file chooser and the EyeDropper API work inside its sandbox; browser storage does not. Details are in docs/openwebui.md.
1. The picker, rendered inline under the tool call | 2. OK: confirm the app's call to |
|
|
3. Confirm the chat message ("I picked …") | 4. The model reads the answer with |
|
|
The Pick tab: a loaded image, a sampled colour | |
|
Capability logging
When a client connects, the server writes a summary to stderr. Some clients surface server stderr: Claude Desktop writes it to mcp-server-feature-test.log, VS Code shows it in the Output panel, and docker logs shows it for containers.
2026-11-08T16:31:40.486Z INFO [client.connected] client connected: smoke-test 0.0.1 (protocol 2025-11-25, legacy era, stdio)
elicitation form: yes url: yes
MCP Apps UI yes mimeTypes: text/html;profile=mcp-app
sampling no
roots no
tasks no
extensions (none besides UI)
experimental (none)
raw {"elicitation":{"form":{},"url":{}},"extensions":{"io.modelcontextprotocol/ui":{"mimeTypes":["text/html;profile=mcp-app"]}}}
2026-11-08T16:31:40.514Z INFO [tool.input_required] elicit_confirm [legacy] asks for input: confirm (form)
2026-11-08T16:31:40.529Z INFO [tool.result] elicit_confirm [legacy] user: confirm=accept; → ok (0 ms)2025-era clients are logged once per connection, after the
initializehandshake (client.connected).2026-07-28 clients have no handshake. They are logged the first time a new combination of client info, version, protocol, transport and capabilities appears in a request envelope (
client.seen). Repeat sightings only update the counters.Each tool call is logged with the user's answer (
accept,declineorcancel) and the outcome (ok,errororcancelled).With
LOG_FORMAT=jsonevery event is one JSON line (time,level,event,msgplus structured fields such assummaryandcapabilities), which is easy to process withjq.list_seen_clientsreturns the same information through MCP, which helps when several frontends are tested against one HTTP server.
Troubleshooting
Symptom | Check |
No dialog appears | Run |
| The client only supports form mode ( |
The URL page doesn't load | In stdio mode the page is served on |
| Some clients (e.g. Open WebUI) answer |
No graphical UI for | Check |
HTTP answers 403 | Host/Origin validation (DNS-rebinding protection). Add your hostname to |
HTTP answers 413, or a Dialog Lab upload fails | The request body was above |
The URL page answers 409 | The flow was already submitted once. Run the tool again for a new link. |
HTTP answers 400 "Missing session" or 404 "Unknown session" | A 2025-era client sent a request without |
| Expected on 2026-07-28 connections. Use |
The client shows garbage or JSON parse errors (stdio) | Something wrote to stdout. This server never does; check wrapper scripts. |
| Run |
Client support
Client support for these features changes quickly, so the server itself is the source of truth: connect your client and read the capability log or inspect_client. This repository tests the server against the official TypeScript SDK client (both protocol eras, stdio and HTTP) and the MCP App against the official AppBridge in headless Chromium. It does not run tests against Claude Desktop, Claude Code, VS Code or Cursor, so their support for form or URL elicitation and MCP Apps is not verified here. For Open WebUI, see the separate notes in docs/openwebui.md.
If you test a client, the client.connected/client.seen log line and the results of elicit_all_field_types (types as received) make a good report.
Development and tests
npm run build # tsc + UI bundle
npm test # build + all suites (unit, integration, UI)
npm run test:unit
npm run test:integration # spawns dist/stdio.js and dist/http.js (free ports)
npm run test:ui # headless Chromium; skipped with a message if none is found
npm run screenshots # regenerates docs/images/*.pngCI (.github/workflows/docker-image.yml) runs the full suite, builds and smoke-tests the image, scans it with Trivy and publishes it; see docs/docker.md. See docs/testing.md for what each suite covers, and docs/architecture.md for how the server is put together.
Source layout: src/server.ts (tools and factory), src/files.ts (generated sample files, upload decoding and limits), src/clients.ts (capability summary and seen-clients registry), src/log.ts (stderr logger), src/flows.ts (URL-elicitation pages), src/httpServer.ts + src/http.ts (HTTP), src/stdio.ts (stdio), src/banner.ts (container startup banner), src/colorPicker.ts (the pick_color tools), src/colorMath.ts (colour maths shared with the picker UI), src/viewer3d.ts (the view_3d tools and the sample GLB), ui/ (the MCP Apps).
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP compatibility and transport verification server.
MCP compatibility and transport verification server.
MCP compatibility and transport verification server.
MCP compatibility and transport verification server.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA test server that exercises all MCP protocol features including prompts, tools, resources, and sampling, intended for MCP client builders.417,840 npmMIT
- AlicenseNot gradedqualityDmaintenanceA test MCP server that exercises all MCP protocol features, including prompts, tools, resources, and sampling, for client builders.417,840 npmMIT
- FlicenseBqualityDmaintenanceA test MCP server that exercises all protocol features including tools, resources, prompts, and sampling to help client builders validate implementations.132-
- AlicenseNot gradedqualityDmaintenanceA demo MCP server showcasing every MCP capability with fake logic, including tools, resources, prompts, progress, cancellation, elicitation, sampling, roots, and subscriptions, over Streamable HTTP, HTTP+SSE, and stdio transports.20 npmMIT











