You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
with APP_RESOURCE_URI imported from src/constants.ts. The static extractor rejects the identifier, so the same string (ui://cargo-hauler/dashboard.html) must now be spelled as a literal in the app route's config.resourceUri, in src/constants.ts (runtime use), and in each tool that wants the widget. Nothing checks they agree.
Ask: let a tool reference the app route it targets (e.g. _meta: { ui: { app: 'hauler/dashboard' } } resolved by the compiler to that app's resourceUri), or allow const string identifiers from the same module in the static grammar.
config.template is project-root relative. In src/mcp/hauler/apps/dashboard.tsx, template: './src/mcp/hauler/apps/dashboard.html' — the path resolves from the project root, not the route file, so moving the app route requires editing the literal. Route-relative resolution (or accepting both with route-relative preferred) would match how every other import in the file resolves.
Minor, same session: agent-bundle inspect --routes aborts on the first diagnostic set instead of emitting the partial route graph, which makes it impossible to verify one route while another is mid-edit.
Static route config can reference an MCP App instead of repeating its ui:// literal — both requested forms:
appResourceUri('<app>'), exported from the new light agent-bundle/routes subpath (types plus this helper; 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 tree is discovered to the target App route's static config.resourceUri. Accepted references: '<app>', '<server>/<app>', 'app:<server>/<app>', or a relative module path (with or without its .ts/.tsx extension). The App must belong to the referencing route's own generated server — a generated server registers only its own Apps. Unknown / other-server / non-MCP-route references are AB4826.
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 (import { APP_RESOURCE_URI } from '../constants'; .ts/.tsx/.js-style/index resolution, one hop, parsed never executed). This is exactly the src/constants.ts scenario from the report, and the value stays available at run time for result _meta.
Everything else stays AB4806, whose message now says why the identifier was rejected and whose recovery names both supported forms.
ToolConfig/ResourceConfig/PromptConfig/AppRouteConfig._meta type ui.resourceUri (RouteMeta, RouteUiMeta; the ui block stays open for the rest of the MCP Apps vocabulary).
New AB4828 (validation): a generated route advertising _meta.ui.resourceUri of an App whose targets are narrower than the server's is rejected, whether referenced or literal.
App route config.template resolves relative to the route module, like its imports. 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, 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, template rule, AB4806/AB4826/AB4827/AB4828), docs/entry-conventions.md, docs/framework-mode.md (App route + tool example). Changeset for agent-bundle (patch, per the pre-1.0 rule).
Not done here: the minor note about agent-bundle inspect --routes aborting on the first diagnostic set instead of emitting the partial route graph — that changes the invalid-inspection result shape / CLI output and is left for a follow-up issue.
Tests
tests/route-config-extract.test.ts: same-module and imported const resolution (incl. .js-style and index specifiers); rejections for package specifier, missing/outside-project module, missing export, non-literal export, type-only and default imports (all AB4806 naming both forms); appResourceUri() placeholder recording and resolution by bare name, qualified id, app: id, relative path (dotted names, .jsx spelling, mistyped suffix rejected); unknown/other-server/non-MCP references → AB4826; helper not imported / wrong specifier / arity / non-string / dynamic argument → AB4806; type-level satisfies ToolConfig with an open ui block.
tests/route-graph.test.ts: cross-route resolution (tool/resource/prompt) with digest sensitivity; AB4826 beside AB4806; same-server rule with custom/conflict/generated-override modes; template route-relative / legacy root-relative / ambiguous / missing / absolute, digest stability; normalized mcpApps[].template; AB4828 for referenced and literal URIs, restricted server, config-declared App.
tests/generated-route-server.test.ts (build level): App route with imported-const resourceUri and route-relative template, tool using appResourceUri('dashboard'), resource importing the same const; the built stdio server lists _meta.ui.resourceUri resolved for both and the compiled App HTML comes from the route-relative template.
Gates: typecheck, lint, test:unit, test:route-unit, test:projection, build + test:integration:run (948 passed), examples/* checks; CI green and Codex review clean on the merged head.
Activity
fix(routes): resolve App references only against generated servers; p…
fix(routes): match relative App references by route-module extension …
fix(routes): keep _meta.ui open-ended; reject Apps not built for ever…
fix(routes): resolve App references only within the referencing route…
feat(routes): reference MCP App resourceUri from static config and re…
fix(routes): resolve App references only against generated servers; p…
fix(routes): match relative App references by route-module extension …
fix(routes): keep _meta.ui open-ended; reject Apps not built for ever…
fix(routes): resolve App references only within the referencing route…
feat(routes): reference MCP App resourceUri from static config and re…
ScriptedAlchemy commentedon Sep 3, 2026
Fixed in #418 (merged as 681fd8d).
What changed
configcan reference an MCP App instead of repeating itsui://literal — both requested forms:appResourceUri('<app>'), exported from the new lightagent-bundle/routessubpath (types plus this helper; 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 tree is discovered to the target App route's staticconfig.resourceUri. Accepted references:'<app>','<server>/<app>','app:<server>/<app>', or a relative module path (with or without its.ts/.tsxextension). The App must belong to the referencing route's own generated server — a generated server registers only its own Apps. Unknown / other-server / non-MCP-route references areAB4826.conststring-literal identifiers — a top-levelconst X = '<literal>'in the route module, orexport const X = '<literal>'from a module reached through a relative import inside the project (import { APP_RESOURCE_URI } from '../constants';.ts/.tsx/.js-style/index resolution, one hop, parsed never executed). This is exactly thesrc/constants.tsscenario from the report, and the value stays available at run time for result_meta.AB4806, whose message now says why the identifier was rejected and whose recovery names both supported forms.ToolConfig/ResourceConfig/PromptConfig/AppRouteConfig._metatypeui.resourceUri(RouteMeta,RouteUiMeta; theuiblock stays open for the rest of the MCP Apps vocabulary).AB4828(validation): a generated route advertising_meta.ui.resourceUriof an App whose targets are narrower than the server's is rejected, whether referenced or literal.config.templateresolves relative to the route module, like its imports. 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,AB4827names 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/diagnostics.md(grammar, template rule,AB4806/AB4826/AB4827/AB4828),docs/entry-conventions.md,docs/framework-mode.md(App route + tool example). Changeset foragent-bundle(patch, per the pre-1.0 rule).Not done here: the minor note about
agent-bundle inspect --routesaborting on the first diagnostic set instead of emitting the partial route graph — that changes the invalid-inspection result shape / CLI output and is left for a follow-up issue.Tests
tests/route-config-extract.test.ts: same-module and imported const resolution (incl..js-style and index specifiers); rejections for package specifier, missing/outside-project module, missing export, non-literal export, type-only and default imports (allAB4806naming both forms);appResourceUri()placeholder recording and resolution by bare name, qualified id,app:id, relative path (dotted names,.jsxspelling, mistyped suffix rejected); unknown/other-server/non-MCP references →AB4826; helper not imported / wrong specifier / arity / non-string / dynamic argument →AB4806; type-levelsatisfies ToolConfigwith an openuiblock.tests/route-graph.test.ts: cross-route resolution (tool/resource/prompt) with digest sensitivity;AB4826besideAB4806; same-server rule with custom/conflict/generated-override modes; template route-relative / legacy root-relative / ambiguous / missing / absolute, digest stability; normalizedmcpApps[].template;AB4828for referenced and literal URIs, restricted server, config-declared App.tests/generated-route-server.test.ts(build level): App route with imported-constresourceUriand route-relative template, tool usingappResourceUri('dashboard'), resource importing the same const; the built stdio server lists_meta.ui.resourceUriresolved for both and the compiled App HTML comes from the route-relative template.examples/*checks; CI green and Codex review clean on the merged head.