Skip to content

serve-app: App falls back to the JSON dump when the opening tool result exceeds 64 KiB (AB8010) — host page re-uploads a result the server already has #562

Description

@ScriptedAlchemy

Symptom

agent-bundle serve-app <server>/<app> (#537) renders the fallback panel instead of the App whenever the opening tool's result is larger than 64 KiB:

hauler/dashboard   MCP App preview failed: AB8010: Request body exceeds 64 KiB.

Reproduced with cargo-hauler hauler dashboard (ScriptedAlchemy/cargo-hauler#83), which spawns agent-bundle serve-app hauler/dashboard --tool hauler_status: on a machine with ~20 active tickets and 24h metrics, hauler_status returns well over 64 KiB, and the page shows the raw JSON dump ("Showing the ordinary tool result instead"). The App is fine; the same server renders in an MCP host.

Root cause

The host page round-trips the tool result through the browser:

  • src/serve-app/serve-mcp-app.ts:328 calls the tool once server-side (session.bridge.callTool) and embeds the whole result in the page seed (:497).
  • src/serve-app/serve-app-page.ts:113 POSTs that seed back — { host, input, previewProfile, result: seed.result, toolName } — to POST /api/mcp/sessions/<id>/apps.
  • src/dev/mcp-apps/mcp-app-routes.ts:296 requires result in that body, and the body is read through readJsonBody with the shared 64 KiB bound (src/dev/http.ts:31-33, AB8010).

So the server refuses to accept back a value it produced itself. The Workbench's own App preview goes through the same route and has the same ceiling for any tool result > 64 KiB; it is just rarer there.

Fix options

  1. Keep the opening { input, result } server-side (serve-app already holds it) and let the page bind by sessionId/toolName only; the route accepts an omitted result when the session has a retained opening result. Minimal, no protocol change for the Workbench.
  2. More generally, bind an App to a server-known tool call (call id from the MCP session service) instead of re-uploading the result. This fixes the Workbench too and removes the client's ability to fabricate a result.
  3. Raising the bound for this one route is not enough: hauler_status can grow unbounded with queue depth.

Whichever lands, the fallback panel should name the real cause ("result too large to rebind" is a framework defect, not an App capability gap), and tests/serve-app.test.ts should cover a >64 KiB opening result.

Related: #514, #537, #558 (the consumer that surfaced it).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmeta-frameworkAgent Bundle compiler-coupled meta-framework

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions