MCP Apps demo server: a stateless report-generator with interactive widgets for analytics reports and player surveys. Demonstrates widget reuse, human gates, and stateless HTTP transport.
Server demonstrates solid tool design with clear naming, comprehensive descriptions, and proper schema definitions. All 7 tools have verb-noun names (generate_report, get_report, create_survey, add_survey_question, remove_survey_question, confirm_create_survey, get_survey) and detailed descriptions (100-300 chars). Input schemas use Zod with proper types and enums. However, output schemas are not formally documented in the tool definitions, responses are returned as text JSON without explicit schema declarations. Error handling is basic (ok/err helpers) without recovery guidance. Tool composition is excellent: stateless design, proper chaining via reportId/surveyId, and idempotent operations. Security is strong: no secrets in parameters, app-only tools properly gated.
Add one or more questions to the current draft survey. Batch related questions into a single call. The already-rendered builder updates with the new list — do not restate the questions in prose. Only the user can confirm the survey, by pressing the Confirm button inside the survey widget — there is deliberately no confirm tool available to you. If asked to confirm or launch the survey, tell the user to review the draft and press Confirm in the widget. The confirmation will arrive as a widget context update.
App-only: the human gate. Called by the survey builder when the user presses Confirm; finalizes the draft with the selected target regions.
Create a DRAFT player survey for Ravenwatch and render the interactive survey builder in the conversation. Add questions with add_survey_question; the user can also add questions and pick target regions directly in the builder. IMPORTANT: Only the user can confirm the survey, by pressing the Confirm button inside the survey widget — there is deliberately no confirm tool available to you. If asked to confirm or launch the survey, tell the user to review the draft and press Confirm in the widget. The confirmation will arrive as a widget context update.
Generate an interactive analytics report for Ravenwatch and render it in the conversation. Topics: 'player-retention' (DAU, D7 retention, session length, quest funnel) or 'q3-revenue' (revenue, ARPDAU, conversion, store items). IMPORTANT: the user's interactions with the rendered report (flagging findings, switching views) are delivered to you as widget context updates — always check the widget context before responding.
Output schemas not formally documented. Tools return text JSON via ok() helper without explicit response schema declarations. LLMs cannot reliably parse or plan downstream calls without knowing expected fields.
Error handling lacks recovery guidance. err() helper returns plain text messages without categorization (retryable vs fatal) or actionable next steps. LLMs cannot determine whether to retry, ask user, or abort.
App-only tools (get_report, confirm_create_survey, get_survey) lack explicit documentation of visibility constraints in descriptions. Users may attempt to call them directly, causing confusion.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | A | 85 | 2026-07-28+ | v2 |
App-only: full data for the current report, fetched by the widget when it mounts.
App-only: full state of the current survey draft, fetched by the builder when it mounts. Long-poll variant: pass sinceVersion + waitMs and the response is held until the draft changes.
Remove one or more questions from the current draft survey, by id. Question ids appear in the results of add_survey_question. The already-rendered builder updates with the new list. Only the user can confirm the survey, by pressing the Confirm button inside the survey widget — there is deliberately no confirm tool available to you. If asked to confirm or launch the survey, tell the user to review the draft and press Confirm in the widget. The confirmation will arrive as a widget context update.
get_survey long-poll parameters (sinceVersion, waitMs) lack range constraints or validation guidance. LLMs may pass invalid values (negative ms, huge version numbers).
Tool composition relies on implicit state threading (reportId, surveyId) via response text. While stateless and correct per 2026-07-28 spec, descriptions could explicitly guide LLMs to extract and reuse these IDs in follow-up calls.