Skip to content

fix(docs): serve the two discovery endpoints the site advertises - #492

Merged
IgorShevchik merged 1 commit into
mainfrom
fix/well-known-discovery
Aug 25, 2026
Merged

fix(docs): serve the two discovery endpoints the site advertises#492
IgorShevchik merged 1 commit into
mainfrom
fix/well-known-discovery

Conversation

@IgorShevchik

Copy link
Copy Markdown
Collaborator

Linked issue

Sync with nuxt/ui@v49ef3ee39 (nuxt/ui#6878), recorded as a skip. Reading it turned up a defect of our own, fixed here. After this the cursor is at upstream HEAD.

Type of change

  • Bug fix (a non-breaking change that fixes an issue)

Description

docs/nuxt.config.ts advertises six discovery endpoints from / in an RFC 8288 Link header. Four are prerendered and present in the static build. Two never existed at all:

</.well-known/api-catalog>;            rel="api-catalog"
</.well-known/mcp/server-card.json>;   rel="service-desc"

Nothing served them — no route under docs/server/routes/, and .output/public/.well-known/ held nothing but skills. raw/index.md.get.ts:24 even names the server-card URL in a comment as though it were there. The headers were adopted without the routes behind them.

Severity, stated plainly: the site ships via nuxt generate to GitHub Pages, where routeRules.headers are not emitted at all — so the advertisement is inert in production and this was never a live 404. It was still a config claiming endpoints the site does not have.

The fix

Both routes now exist and are prerendered, so they land in the static build beside the four the same header already names. The convention here is "advertise what we prerender"; these two were simply the outliers.

  • api-catalog — an RFC 9727 linkset naming only what this site actually serves. Upstream anchors an openapi.json in theirs; we have none, so it is absent by construction rather than by oversight. service-doc points at /docs/getting-started/ because this fork has no MCP docs page — nuxt.config.ts:710 already carries that path commented out for the same reason.
  • server-card.json — reads its tool, resource and prompt lists from the running server via listMcpDefinitions, so the card cannot drift from what docs/server/mcp/ registers.

That listing resolves through the #nuxt-mcp-toolkit/tools.mjs virtual module, which is not available during prerender — the first attempt failed the build outright with Package import specifier "#nuxt-mcp-toolkit/tools.mjs" is not defined. Since the card has to exist on static hosting, the import is attempted and degrades: served by a real server it carries the full catalogue, prerendered it omits those three arrays. A card without them is still valid — a client discovers the catalogue by calling tools/list on the endpoint, which is the normal MCP flow.

Why the upstream commit itself is skipped

Its 1387 lines of agent-readiness plumbing re-decide architecture this fork already has. docs/server/mcp/ carries 27 files — 12 tools, 4 resources, 2 prompts — against upstream's smaller set, wired through @nuxtjs/mcp-toolkit at /mcp/. The OpenAPI half describes upstream's /api/** surface, which is not ours. Skipped on maintainer decision.

Verification

Against the build, not the source:

  • docs:generate goes 1262 → 1264 routes; the run that failed on the virtual-module import is what drove the degradation above.
  • Both files land with correct absolute URLs, and serverInfo.version resolves to 2.12.0 from pkg.version.
  • Every href the catalogue names was resolved against the output — all present, the single exception being /mcp/ itself, which is a live server route rather than a static file.
  • All six endpoints the Link header advertises now exist.

lint · typecheck · test (7168 passed, 6 skipped, 314 files) · docs:generate — green.

Ledger: cursor → 9ef3ee39, one entry with its .sync/log/ journal, parity snapshot refreshed (zero package differences).

Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

Generated by Claude Code

`docs/nuxt.config.ts` advertises six discovery endpoints from `/` in an RFC 8288
`Link` header. Four are prerendered and present in the static build. **Two never
existed at all** — nothing served `/.well-known/api-catalog` or
`/.well-known/mcp/server-card.json`, and `.output/public/.well-known/` held
nothing but `skills`. `raw/index.md.get.ts:24` even names the server-card URL in
a comment as though it were there. The headers were adopted without the routes
behind them.

Severity, stated plainly: the site ships via `nuxt generate` to GitHub Pages,
where `routeRules.headers` are not emitted, so the advertisement is inert in
production and this was never a live 404. It was still a config claiming
endpoints the site does not have.

Both routes now exist and are prerendered, so they land in the static build
beside the four the same header already names — the convention here is
"advertise what we prerender", and these two were the outliers.

- **`api-catalog`** is an RFC 9727 linkset naming only what this site serves.
  Upstream anchors an `openapi.json` in theirs; we have none, so it is absent by
  construction rather than by oversight. `service-doc` points at
  `/docs/getting-started/` because this fork has no MCP docs page —
  `nuxt.config.ts:710` already carries that path commented out for the same
  reason.
- **`server-card.json`** reads its tool, resource and prompt lists from the
  running server via `listMcpDefinitions`, so the card cannot drift from what
  `docs/server/mcp/` registers.

That listing resolves through the `#nuxt-mcp-toolkit/tools.mjs` virtual module,
which is **not available during prerender** — the first attempt failed the build
outright with `Package import specifier "#nuxt-mcp-toolkit/tools.mjs" is not
defined`. Since the card has to exist on static hosting, the import is attempted
and degrades: served by a real server it carries the full catalogue, prerendered
it omits those three arrays. A card without them is still valid — a client
discovers the catalogue by calling `tools/list` on the endpoint, which is the
normal MCP flow.

Found while reading upstream `9ef3ee39` (#6878), which is recorded as a **skip**:
its 1387 lines of agent-readiness plumbing re-decide architecture this fork
already has — `docs/server/mcp/` carries 27 files against upstream's smaller set,
and the OpenAPI half describes their `/api/**` surface, not ours.

Verified against the build, not the source: `docs:generate` goes 1262 → 1264
routes, both files land with correct absolute URLs and `serverInfo.version`
resolving to `2.12.0`, and every href the catalogue names resolves against the
output — all present, the one exception being `/mcp/` itself, a live server route
rather than a static file. All six advertised endpoints now exist.

Ledger: cursor → `9ef3ee39` (upstream HEAD), parity snapshot refreshed.
@IgorShevchik
IgorShevchik merged commit 820f0ef into main Aug 25, 2026
2 checks passed
@IgorShevchik
IgorShevchik deleted the fix/well-known-discovery branch August 25, 2026 09:37
IgorShevchik pushed a commit that referenced this pull request Aug 25, 2026
The entry was written with `pending-merge` because the PR carrying it had not
merged yet; it now points at #492 and its squash SHA `820f0efb`. No entry in the
ledger is left unreconciled, and the cursor `9ef3ee39` is upstream HEAD.

Bookkeeping only — no source, test or docs change.
IgorShevchik added a commit that referenced this pull request Aug 25, 2026
The entry was written with `pending-merge` because the PR carrying it had not
merged yet; it now points at #492 and its squash SHA `820f0efb`. No entry in the
ledger is left unreconciled, and the cursor `9ef3ee39` is upstream HEAD.

Bookkeeping only — no source, test or docs change.

Co-authored-by: Shevchik Igor <noreply@anthropic.com>
IgorShevchik added a commit that referenced this pull request Aug 29, 2026
…humb (#509)

* fix(Form,Range): omit method on nested forms, emit a number for one thumb

Ports two upstream fixes, contiguous in `v4`: `a494a97d` (nuxt/ui #6888) and
`3d2de0ce` (nuxt/ui #6890).

**`Form` — `method` on a nested form.** Our root element already renders as a
`div` when nested (`:is="parentBus ? 'div' : 'form'"`), and `:name` was already
conditional on the same flag — but `method="post"` was left unconditional, so a
nested form emitted `<div method="post">`. Upstream's fix is the line we were
missing: `:method="parentBus ? undefined : 'post'"`.

**`Range` — a single thumb emitted an array, twice.** Upstream's `Slider` is
this fork's `Range` (§1). `useForwardProps` was handed `emits`, so `SliderRoot`'s
own `update:modelValue` was re-emitted alongside the one the component derives —
`[[1], [1]]` in our own test, and an array rather than a number for a single
thumb. Dropping the `emits` argument leaves the component's `defineModel`
handling as the only emitter.

Ported upstream's two new emits cases and the corrected expectation, adapted to
`Range`. Mutation-checked rather than assumed: restoring the `emits` argument
with the tests kept turns **all six** red across both projects.

Verified with `CI=true`: `lint` · `typecheck` · `test` (7472 passed, 6 skipped,
318 files) · `docs:generate` (1264 routes).

Ledger: cursor → `3d2de0ce`, two entries.

* chore(sync): record the agent-discovery refactor as skipped

Advances the cursor past `ae243116` (nuxt/ui #6883) and adds the journals for
this run's three commits.

`ae243116` replaces upstream's hand-rolled agent-discovery surface with a
`nuxt-agent-discovery` module, deleting its own `.well-known`, `raw/*`,
`sitemap.*`, markdown-negotiation and error-handling implementation in the
process — 33 files, +474/−1914.

Skipped: it refactors infrastructure this fork deliberately does not have.
`9ef3ee39`, the commit that built that surface, is recorded one entry earlier as
a skip on maintainer decision, so a refactor of code we never took has nothing to
apply to. Taking it would also delete working code written on purpose — the two
`.well-known` routes it removes are the ones this fork **added** in #492, and our
`raw/*` and `sitemap.*` routes are in use: `raw/**.md` is what the skills
reference links to, and both sitemaps are prerendered into the static build.

Adopting the module stays a live option, but that is a decision about our own
architecture rather than a port.

Ledger: cursor → `ae243116` (upstream HEAD), parity snapshot refreshed.

---------

Co-authored-by: Shevchik Igor <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants