Repository navigation
feat(dev): add mcp-server-examples with the reference view and form flows - #349
Merged
Merged
Conversation
@transcend-io/airgap.js-types
@transcend-io/cli
@transcend-io/design-tokens
@transcend-io/internationalization
@transcend-io/privacy-types
@transcend-io/sdk
@transcend-io/type-utils
@transcend-io/utils
@transcend-io/mcp
@transcend-io/mcp-server-admin
@transcend-io/mcp-server-assessment
@transcend-io/mcp-server-base
@transcend-io/mcp-server-consent
@transcend-io/mcp-server-discovery
@transcend-io/mcp-server-docs
@transcend-io/mcp-server-dsr
@transcend-io/mcp-server-inventory
@transcend-io/mcp-server-preferences
@transcend-io/mcp-server-workflows
commit: |
This was referenced Aug 2, 2026
dsklyar
force-pushed
the
danielsklyar/zel-8132-mcp-server-examples
branch
from
August 3, 2026 06:02
4d97e09 to
096123f
Compare
dsklyar
changed the base branch from
danielsklyar/zel-8129-vite-view-build-pipeline
to
danielsklyar/zel-8113-inspector-sandbox-proxy
August 3, 2026 06:03
This was referenced Aug 3, 2026
dsklyar
force-pushed
the
danielsklyar/zel-8132-mcp-server-examples
branch
from
August 3, 2026 23:47
096123f to
e96624f
Compare
dsklyar
force-pushed
the
danielsklyar/zel-8132-mcp-server-examples
branch
from
August 4, 2026 20:24
e96624f to
51d5158
Compare
dsklyar
force-pushed
the
danielsklyar/zel-8132-mcp-server-examples
branch
from
August 5, 2026 22:33
51d5158 to
c001913
Compare
giacaglia
previously approved these changes
Aug 5, 2026
| import { HELLO_APP_RESOURCE } from '../apps/hello.js'; | ||
|
|
||
| /** Prompt shown above the elicitation form. */ | ||
| const HELLO_ELICIT_MESSAGE = 'Who should this greeting be addressed to?'; |
Contributor
Author
There was a problem hiding this comment.
WDYM, this is an example for what configuration could look like.
dawson-turechek-transcend
previously approved these changes
Aug 6, 2026
dawson-turechek-transcend
left a comment
Member
There was a problem hiding this comment.
Love having these examples!
Base automatically changed from
danielsklyar/zel-8113-inspector-sandbox-proxy
to
main
August 6, 2026 22:21
dsklyar
dismissed stale reviews from dawson-turechek-transcend and giacaglia
via
August 6, 2026 22:22
06dcd2e
dsklyar
force-pushed
the
danielsklyar/zel-8132-mcp-server-examples
branch
from
August 6, 2026 22:22
c001913 to
06dcd2e
Compare
Replaces the bespoke generateBundle plugin with rolldown's own `sourcemapExcludeSources`, in a new `tsdown.config.mcp.ts` that the MCP servers extend. The `.html` loader moves there too, since both settings exist for the same fact: a prebuilt view becomes one large string literal that a sourcemap would otherwise embed a second time. Scoped to MCP servers rather than set in the base config, so published libraries keep their embedded sources. Node reads sources from disk when they are absent from a map, so a server debugged beside its own `src` produces an identical stack trace. Maps across the MCP packages drop from ~817 KB to ~174 KB, and `tsdown.config.base.ts` returns to what main has.
The root config taught every package's tests to read `.html` as text, but the only module-level `.html` import in the repo is a generated MCP App view. Move the loader to `vitest.config.mcp.ts`, which MCP servers opt into through their `test` script, and restore the root config to its `.svg`-only form. Enforced rather than documented: a package that builds a view but tests on the root config would fail only once a test imported that view, reporting invalid JS syntax in an HTML file. The new convention test keys off `build:ui` so it also covers `dev/*`, which the publishable-package conventions skip.
The tsdown rewiring touches eleven publishable packages and changes what their published maps contain, so the release check is right to ask for one.
Removes the arbitrary color and length scan along with the README sentence that promised it, leaving the styling rules as documented convention.
…-mcp-server-examples
Review fixes for the examples server and the configs around it.
example_elicitation parsed a host's answer with the all-optional tool schema,
so `{ action: 'accept', content: {} }` reported `answered` with nothing in it —
indistinguishable from a filled-in form, in the one file whose purpose is
keeping those endings apart. Answers are now parsed against a schema that
requires what the form required, with the mask checked against REQUIRED_FIELDS
so the two cannot drift.
Also from review:
- Drop the README clause citing `scripts/mcp-app-views.test.ts`, which lands
with the Inspector loop rather than here.
- Remove the examples `typecheck` -> `build` override. The `.html` ambient
declaration is a wildcard, so tsc resolves it without the document on disk;
only `test`, which reads the file, needs the build.
- Cover `dev/*` in `check:deps:root`, so a catalog drift there is caught.
- Reframe the sourcemap change as the size win it is. No published server
inlines a view today, so a doubly-embedded view was never the cause.
- Name the command when a view has not been built, instead of a bare ENOENT.
Same facts, fewer lines: each block keeps the constraint a reader cannot get from the code and drops the restatement around it. Net 62 comment lines.
The measured sizes and the "no published server inlines a view today" claim were both true when written and wrong the moment a package changes. The durable reason stays in the comment; the measurement belongs to the changeset, which describes a single release.
Naming the examples package dates the comment as soon as another server inlines a view, which is the point of putting the loader in a shared config.
dawson-turechek-transcend
approved these changes
Aug 7, 2026
3 tasks
4 tasks
This was referenced Sep 7, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
dev/mcp-server-examples, a private package that is the first real consumer of everything below it in this stack — and the thing that proves the render path actually works, since the pipeline and the serving code both landed with no view to exercise them.Two worked examples:
example_hello_apptakes all three paths: plain text for a scripted client, a form for an elicitation host, and the interactivehelloview plus an app-only refresh tool for an MCP Apps host. The view covers what a static document cannot — React state, atools/callround trip from inside the iframe, and re-rendering from the result the host pushes back.example_elicitationis form collection on its own, and deliberately has no MCP App variant. Precedence is app, then form, then baseline, so a tool offering both resolves to its view on every host worth testing against — form-only is what keeps this flow reachable from a host that renders views instead of only from one that cannot. It covers every field shape the spec allows, including the titledoneOfselect andanyOfmulti-select that are the only nested structures permitted, and reports a distinct outcome for each way a request can end. Declining and cancelling stay separate because a refusal should not be retried while an abandoned dialog reasonably can be.Why
dev/and not a published packageA view ships as one self-contained document — React, the view's CSS, and the design tokens all inlined — at roughly 550 KB. While this demo lived in
@transcend-io/mcp-server-docsit was 94% of that package's published bytes, downloaded by everyone installing the umbrella server or the CLI, for a tool no end user has a reason to call.private: trueindev/makes that structural instead of a rule someone has to remember, and it is whypnpm-workspace.yamlgainsdev/*outsidepackages/.Being the first package to inline a built view, it is also the first to need tsdown's
.htmltext loader. Both settings live intsdown.config.mcp.ts, which the MCP servers extend: rolldown's ownsourcemapExcludeSourcesmakes their maps reference sources instead of embedding them, taking the maps across those packages from ~817 kB to ~174 kB — a size win over the ordinary TypeScript these servers are built from, since no published server inlines a view today. Scoped there rather than in the base config so published libraries keep their embedded sources — and since Node reads a source from disk when the map omits it, a server debugged beside its ownsrcstill produces an identical stack trace.Ticket: ZEL-8132. Ninth of eleven PRs splitting the MCP Apps branch. Carries a patch changeset for the eleven MCP servers, whose published sourcemaps change; the examples package itself is private and publishes nothing.
Two deviations from the split plan, worth knowing
scripts/mcp-app-views.test.tsmoved to the next PR. It importsdiscoverMcpPackages, which is part of the Inspector lib rather than this package, so it cannot compile here.src/apps/hello.tsinlines the built document directly rather than callingviewHtml(...). That helper arrives with the Inspector loop in the next PR, which switches this over.Where this sits in the stack
Eleven layers, each targeting the one below it, registered as a GitHub stack — so this diff is only its own commits, and merging a lower layer rebases and retargets everything above it automatically.
tokens.cssfrom source inside the monorepoui://resources and per-capability tool variants./uisubpath withuseMcpAppdev/mcp-server-examples, the first consumer of all of it ← this PRpnpm mcp:inspectwith per-request dev view HTMLpnpm mcp:new-viewscaffolderDepends on #347 for the view build and #344 for the serving code — this is the first consumer of both. Everything below that is ordering, not need.
Test plan
format,lint,typecheck,typecheck:ui, and the fulltestrun are green; the examples package's two test files all run@modelcontextprotocol/inspector@2 --clireports{"hasApp":true,"toolName":"example_hello_app","resourceUri":"ui://transcend-examples/hello","resourceMimeType":"text/html;profile=mcp-app"}and{"hasApp":false,"toolName":"example_elicitation"}, with the server logginghost: mcp-inspector, capabilities: ["MCP_APP"].resources/readreturns the document, and the app-only refresh tool is correctly absent fromtools/list.example_elicitationfrom that CLI returns"outcome": "unavailable"with"echo": "ping ping"— the baseline branch echoing the agent's own arguments rather than inventing any, since the CLI declares no elicitation supportDemo(s)
Running
pnpm mcp:inspectScreen.Recording.2026-08-02.at.23.14.23.mov
Running
pnpm mcp:inspect --examlesScreen.Recording.2026-08-02.at.23.14.51.mov