Skip to content

feat(routes): reference MCP App resourceUri from static config and resolve App templates route-relative (#388) - #418

Merged
ScriptedAlchemy merged 5 commits into
mainfrom
fix/388-route-config-references
Sep 3, 2026
Merged

feat(routes): reference MCP App resourceUri from static config and resolve App templates route-relative (#388)#418
ScriptedAlchemy merged 5 commits into
mainfrom
fix/388-route-config-references

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #388.

  • Static config may reference an MCP App instead of repeating its ui:// literal. Two constrained reference forms join the static route-config grammar (packages/agent-bundle/src/routes/config-extract.ts):
    • appResourceUri('<app>') — a compile-time helper exported from the new light agent-bundle/routes subpath (src/routes/public.ts; 545-byte chunk with no imports, so a route module can import it at run time without pulling the compiler into its generated bundle). The route-graph compiler resolves it after the whole tree is discovered to the target App route's config.resourceUri; accepted references are '<app>' (same server), '<server>/<app>', 'app:<server>/<app>', or a relative module path. An unknown App is the new AB4826 (message lists known App route ids).
    • const string-literal identifiers — a top-level const X = '<literal>' in the route module, or export const X = '<literal>' from a module reached through a relative import inside the project root (.ts/.tsx/.js-style/index resolution, one hop, parsed never executed). This is the issue's APP_RESOURCE_URI from src/constants.ts scenario and stays available at run time (result _meta).
    • Everything else stays AB4806, with messages that now say why the identifier was rejected and a recovery that names both supported forms.
  • _meta.ui.resourceUri typing: ToolConfig/ResourceConfig/PromptConfig/AppRouteConfig._meta are RouteMeta (Record<string, unknown> & { ui?: RouteUiMeta }), exported from agent-bundle and agent-bundle/routes.
  • config.template is route-file-relative (src/routes/app-template.ts, used by routes/graph.ts and config/normalize.ts), matching how imports resolve. The legacy project-root-relative form is still accepted with no diagnostic while it is the only interpretation naming an existing file. When both interpretations name different existing files, or neither exists, the new AB4827 names both candidate paths and the fix. The IR keeps the authored path (digest stays machine-independent); the normalized model carries the resolved absolute file.
  • Docs: docs/diagnostics.md (grammar paragraph, template rule, AB4806 row, new AB4826/AB4827 rows), docs/entry-conventions.md (apps row), docs/framework-mode.md (App route + tool example, _meta row). Changeset .changeset/388-route-config-references.md (minor, new public helper/subpath).
  • Codes verified unused in origin/main and open PRs (feat(routes): conventional shared layout module for rendered routes (#312) #396 holds AB4830AB4832; AB4826/AB4827 taken here).

Not done (scope): the issue's minor note about agent-bundle inspect --routes aborting on diagnostics instead of emitting the partial graph — that requires changing the invalid-inspection result shape/CLI output and is left for a follow-up.

examples/mcp-app needs no change: it uses a config-declared App (config entry/template correctly resolve from the project root, where the config file lives) and reads app.resourceUri from agent-bundle/mcp-apps, so nothing duplicates the literal. Its check (pnpm --filter @agent-bundle-example/mcp-app check) passes.

Evidence

  • pnpm typecheck — pass.
  • pnpm lint — 0 errors / 0 warnings (1047 files).
  • pnpm test:unit — 2755 passed, 2 failed: mcp-probe-service "timed-out probe remained blocked on teardown" and native-claude-contract "fails closed when the candidate plugin…" (5 s timeout). Both are unrelated and environmental: the Claude one hashes the real ~/.claude/plugins tree (324 MB / 1432 files here) and fails identically on a pristine origin/main worktree; the probe one passed on isolated rerun.
  • pnpm test:route-unit — 36 passed, 1 failed (lifecycle-replay 5 s timeout) → passed on isolated rerun.
  • pnpm test:projection — 66 passed.
  • pnpm build && pnpm test:integration:run — 948 passed, 0 failed.
  • New build-level test (generated-route-server.test.ts, "Static route config grammar forbids identifier references, so an MCP App's resourceUri must be duplicated as a literal in every tool's _meta.ui.resourceUri; config.template resolves from the project root #388") passes: an App route with an imported-const resourceUri and a route-relative template, a tool using appResourceUri('dashboard'), and a resource importing the same const; the built server lists _meta.ui.resourceUri resolved for both and the compiled App HTML comes from the route-relative template.

Test plan

  • tests/route-config-extract.test.ts: same-module const; imported const (.js-style and index specifiers); rejections for package specifier, missing module, outside-project module, missing export, non-literal export, type-only import, default import (all AB4806 naming both forms); appResourceUri() placeholder recording (paths + positions) and resolution by bare name, qualified id, app: id, relative path with/without extension; unknown App → AB4826 (+ bare-form hint outside MCP routes); helper not imported / wrong specifier / non-string / arity / dynamic argument → AB4806.
  • tests/route-graph.test.ts: cross-route resolution (tool, resource, prompt, cross-server tool) to the App URI incl. digest sensitivity; AB4826 + AB4806 side by side; template route-relative / legacy root-relative (no diagnostic) / ambiguous (AB4827 names both) / missing (AB4827) and digest stability; normalized mcpApps[].template for route-relative and legacy, validate/inspect invalid on ambiguity.
  • tests/generated-route-server.test.ts: end-to-end build + stdio listing as above.
  • pnpm --filter @agent-bundle-example/mcp-app check passes.

@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4a83878

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T10:27:05.527159Z 4a83878 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 511ee564fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .changeset/388-route-config-references.md Outdated
Comment thread .changeset/388-route-config-references.md Outdated
Comment thread packages/agent-bundle/src/routes/graph.ts Outdated
@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@418
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@418
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@418

commit: 4a83878

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4590613843

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/agent-bundle/src/routes/config-extract.ts Outdated
Comment thread packages/agent-bundle/src/routes/app-template.ts Outdated
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1eda1aafe2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/agent-bundle/src/routes/public.ts
Comment thread packages/agent-bundle/src/routes/graph.ts
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38cea8d5e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/agent-bundle/src/routes/config-extract.ts
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 8c0ee74332

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…solve App templates route-relative (#388)

Static route config may now reference an App instead of repeating its
ui:// literal: `appResourceUri('<app>')` from the new light
`agent-bundle/routes` subpath resolves at graph-compile time to the App
route's config.resourceUri (AB4826 for an unknown App), and top-level
const string-literal identifiers — declared locally or `export const`-ed
by a relative sibling module — extract statically; AB4806 names both
forms. `_meta.ui.resourceUri` is typed through RouteMeta/RouteUiMeta.

App route config.template resolves relative to the route module like its
imports; the legacy project-root-relative form stays accepted while
unambiguous, and AB4827 names both candidate paths otherwise.
…atch changeset (#388 review)

Apps of servers packaged as custom/command/remote or left in an AB4800
conflict are never built, so appResourceUri() must not resolve to them
(AB4826 instead). Server-mode decision is shared between reference
resolution and server assembly. Changeset follows the pre-1.0 rule
(patch for additive changes) and ends with the PR marker.
…only; probe absolute templates (#388 review)

A relative appResourceUri() reference strips only .ts/.tsx (or the
.js/.jsx spelling of them), so dotted App names keep their dot and a
mistyped suffix matches nothing. A coincident (absolute) template
candidate is probed for existence so a missing file is AB4827 rather
than a later bundler failure.
…y server target (AB4828) (#388 review)

RouteUiMeta carries an index signature so the rest of the MCP Apps ui
vocabulary (prefersBorder, csp, permissions) still satisfies ToolConfig.
Validation adds AB4828: a generated route advertising _meta.ui.resourceUri
of an App whose targets are narrower than the server's is rejected,
whether the URI came from appResourceUri() or was written as a literal.
…'s own server (#388 review)

A generated server registers exactly its own Apps, so a cross-server
reference (even in the qualified '<server>/<app>' form) is AB4826 naming
the foreign App; references from non-MCP routes are AB4826 too. Routes
of servers that are not generated ship no config, so their references are
left as authored instead of adding noise beside the mode diagnostic.
@ScriptedAlchemy
ScriptedAlchemy force-pushed the fix/388-route-config-references branch from 8c0ee74 to 4a83878 Compare September 3, 2026 10:20
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 4a83878f04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant