Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/remove-workbench-runtime-app-renderer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agent-bundle": patch
---

Remove the unused runtime MCP App renderer from the bundled Workbench. App previews keep rendering through the server-issued sandbox frame; the package no longer ships `dist/workbench/src/mcp/APP-RENDERER-LICENSE`, and `NOTICE` and `THIRD_PARTY_NOTICES` drop the MCP Inspector `AppRenderer` attribution. (#845)
7 changes: 3 additions & 4 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ LICENSE file distributed with it.
This distribution includes third-party material that is covered by its own
license and notices, which are preserved unmodified alongside that material:

- The Agent Bundle Workbench MCP App renderer is derived from the MCP
Inspector project (MIT License). See THIRD_PARTY_NOTICES and
src/mcp/APP-RENDERER-LICENSE, which the agent-bundle package ships under
dist/workbench/.
- The Agent Bundle Workbench bundles the xterm.js terminal emulator (MIT
License). See THIRD_PARTY_NOTICES, which the agent-bundle package ships
under dist/workbench/.

- The rsc-markdown-stream package (packages/rsc-markdown-stream) was
imported from https://github.com/ScriptedAlchemy/rsc-markdown-stream at
Expand Down
42 changes: 14 additions & 28 deletions docs/architecture/rsc-runtime-workbench.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,21 @@ packages/
tests/host-adapters.native.test.ts
tests/host-adapters.test.ts
tests/mcp-app-binding-service.test.ts
tests/mcp-app-bridge-cancellation.test.ts
tests/mcp-app-bridge.test.ts
tests/mcp-app-diagnostics.test.ts
tests/mcp-app-host-profiles.test.ts
tests/mcp-app-metadata.test.ts
tests/mcp-app-preview-service.test.ts
tests/mcp-app-routes.test.ts
tests/mcp-app-runtime-binding-service.test.ts
tests/mcp-app-runtime-preview-service.test.ts
tests/mcp-app-sandbox.test.ts
tests/mcp-apps-compile.test.ts
tests/mcp-session-routes.test.ts
tests/mcp-session-service.test.ts
tests/mcp-session-trace-publisher.test.ts
tests/native-host-sessions.test.ts
tests/normalization.test.ts
tests/playground-service.test.ts
tests/portable-adapter.test.ts
Expand All @@ -91,21 +96,13 @@ packages/
scripts/capture-runtime-playground.mjs
src/main.tsx
src/mcp/mcp-app-client.ts
src/mcp/mcp-app-frame.tsx
src/mcp/mcp-app-preview.tsx
src/mcp/mcp-page.tsx
src/mcp/mcp-session-controller.ts
src/mcp/mcp-session-model.ts
src/mcp/runtime-app-bridge.ts
src/mcp/runtime-consent-dialog.tsx
src/mcp/runtime-consent-queue.ts
src/mcp/runtime-mcp-handoff.ts
src/project-client.ts
src/runtime-client.ts
src/runtime-inspector.tsx
src/runtime-model.ts
src/runtime-playground.tsx
src/runtime-stage.tsx
src/styles.css
tests/helpers/runtime-playground-fixture.ts
tests/mcp-app-client.test.ts
Expand All @@ -117,21 +114,11 @@ packages/
tests/mcp-session-controller.test.ts
tests/mcp-session-model.test.ts
tests/mcp-session-timeout.e2e.test.ts
tests/runtime-app-bridge.test.ts
tests/runtime-backend.test.ts
tests/runtime-client.test.ts
tests/runtime-consent-dialog.test.ts
tests/runtime-consent-queue.test.ts
tests/runtime-contract-compile.test.ts
tests/runtime-document-atoms-disposal.test.ts
tests/runtime-inspector.test.ts
tests/runtime-mcp-handoff.test.ts
tests/runtime-controller.test.ts
tests/runtime-model.test.ts
tests/runtime-playground-capture-cleanup.test.ts
tests/runtime-playground-capture.test.ts
tests/runtime-playground-hmr.e2e.test.ts
tests/runtime-playground.e2e.test.ts
tests/runtime-playground.test.ts
tests/runtime-stage.test.ts
examples/
rsc-agent-runtime/
package.json
Expand All @@ -144,7 +131,9 @@ examples/
src/build/serialize-definition.ts
src/definition.ts
src/dev/canonical-json.ts
src/dev/compile-diagnostics.ts
src/dev/definition-entry.ts
src/dev/durable-tree.ts
src/dev/environment-checkpoint-store.ts
src/dev/generation-materializer.ts
src/dev/inspection-security.ts
Expand All @@ -171,7 +160,6 @@ examples/
src/runtime/contracts.ts
src/runtime/state-definition.ts
src/runtime/state-file.ts
src/types/mcp-ext-apps-react.d.ts
src/types/react-server-dom-rspack.d.ts
src/types/styles.d.ts
src/widget/App.tsx
Expand All @@ -186,7 +174,6 @@ examples/
tests/host-artifacts.test.ts
tests/host-extensions.test.tsx
tests/http-security.test.ts
tests/mcp-lowering.test.tsx
tests/mcp-transports.integration.test.ts
tests/rsc-hook.integration.test.ts
tests/runtime-artifact-manifest.test.ts
Expand Down Expand Up @@ -251,12 +238,11 @@ are never gated. `ProjectStatus.hostAdoption` exposes the adopted epoch and the
latest evaluation, and the Overview renders it as **Host adoption** beside the
published build, so a rejected epoch is visible rather than silently skipped.

The RSC result tree is not the MCP App document. A current preview moves through
`McpAppPreview`, `SecureAppRenderer`, the official App renderer, the
generation-bound bridge, and the runtime client-surface proxy to an opaque-origin
App iframe. The direct frame, bridge, handoff, proxy, message-limit, binding,
preview-service, routes, mounted-page, and real-browser tests retained above
are the single lifecycle boundary for that binding.
The RSC result tree is not the MCP App document. An App route preview moves
through `McpAppPreview`, which mounts the server-issued sandbox proxy iframe and
drives it with the frame relay (`web-host/browser/frame-relay.ts`) over the
Workbench App routes. The frame-relay, preview, routes, mounted-page, and
real-browser tests retained above are the lifecycle boundary for that binding.

Portable is the baseline. ChatGPT/OpenAI and Claude Workbench profiles are local
compatibility simulations, not vendor certification. Native terminal evidence
Expand Down
3 changes: 1 addition & 2 deletions packages/agent-bundle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1139,8 +1139,7 @@ harness.
and Codex selections are refused when it is configured.
- Raw HTML, JSX/MDX, and Mermaid in Skill Markdown are inert in the workbench renderer.

Third-party notices, including the MIT license and provenance of the MCP App renderer derived from
the MCP Inspector's `AppRenderer`, ship in the published package.
Third-party notices for material bundled into the workbench ship in the published package.

## License

Expand Down
2 changes: 1 addition & 1 deletion packages/agent-bundle/src/dev/mcp-apps/mcp-app-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { runtimeAppMessageLimits } from '../runtime-app-message-limits.ts';
// A force-close DELETE that lands after an accepted graceful close must stay
// idempotent (200, not 404), so this window has to dominate the frame relay's
// force-close budget — clients may fall back as late as their closeTimeoutMs,
// which mcp-app-frame.tsx caps at 30s.
// which web-host/browser/frame-relay.ts caps at 30s.
const gracefulCloseReceiptTimeoutMs = 35_000;

interface CreateRoute {
Expand Down
6 changes: 3 additions & 3 deletions packages/agent-bundle/src/dev/workbench-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ const packageRoot = basename(import.meta.dirname) === 'dist'

const defaultRoot = (): string => resolve(packageRoot, 'dist', 'workbench');

// The Workbench build copies its attribution files into the asset tree without
// an extension (`THIRD_PARTY_NOTICES`, `src/mcp/APP-RENDERER-LICENSE`). Those
// conventional names are plain text a browser should render; every other
// The Workbench build copies its attribution file into the asset tree without
// an extension (`THIRD_PARTY_NOTICES`). Such conventional license and notice
// names are plain text a browser should render; every other
// extensionless file keeps the binary fallback.
const noticeFileName = /^(?:[a-z0-9]+[-_])*(?:licen[cs]e|notices?|copying)$/iu;

Expand Down
9 changes: 3 additions & 6 deletions packages/agent-bundle/tests/dev-workbench-packaging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const execFile = promisify(executeFile);
const workspaceRoot = process.cwd();
const packageRoot = join(workspaceRoot, 'packages', 'agent-bundle');
const workbenchRoot = join(workspaceRoot, 'packages', 'workbench');
const appRendererLicense = join('src', 'mcp', 'APP-RENDERER-LICENSE');
let built: Promise<void> | undefined;

const buildPackage = async (): Promise<void> => {
Expand All @@ -27,17 +26,16 @@ describe.sequential('workbench package build', () => {
const hashedWorkbenchBundle = (kind: 'css' | 'js'): RegExp =>
kind === 'css' ? /^index\.[a-f0-9]{8}\.css$/u : /^index\.[a-f0-9]{8}\.js$/u;

it('copies content-hashed prebuilt workbench assets and the exact app-renderer license into the package distribution', async () => {
it('copies content-hashed prebuilt workbench assets and third-party notices into the package distribution', async () => {
await buildPackage();

await expect(access(join(packageRoot, 'dist', 'workbench', 'index.html'))).resolves.toBeUndefined();
const jsRoot = join(packageRoot, 'dist', 'workbench', 'static', 'js');
const hashedJs = (await readdir(jsRoot)).find((name) => hashedWorkbenchBundle('js').test(name));
if (hashedJs === undefined) throw new Error('Expected a content-hashed workbench index.js.');
await expect(readFile(join(jsRoot, hashedJs), 'utf8')).resolves.toContain('Workbench navigation');
await expect(readFile(join(packageRoot, 'dist', 'workbench', 'THIRD_PARTY_NOTICES'), 'utf8')).resolves.toContain('MCP Inspector');
await expect(readFile(join(packageRoot, 'dist', 'workbench', appRendererLicense), 'utf8')).resolves.toBe(
await readFile(join(workbenchRoot, appRendererLicense), 'utf8'),
await expect(readFile(join(packageRoot, 'dist', 'workbench', 'THIRD_PARTY_NOTICES'), 'utf8')).resolves.toBe(
await readFile(join(workbenchRoot, 'THIRD_PARTY_NOTICES'), 'utf8'),
);
}, 60_000);

Expand Down Expand Up @@ -76,7 +74,6 @@ it('serves prebuilt workbench assets from an installed tarball without the repos
const listing = await execFile('tar', ['-tf', tarball]);
expect(listing.stdout).toContain('package/dist/workbench/index.html');
expect(listing.stdout).toContain('package/dist/workbench/THIRD_PARTY_NOTICES');
expect(listing.stdout).toContain('package/dist/workbench/src/mcp/APP-RENDERER-LICENSE');
expect(listing.stdout).not.toMatch(/package\/dist\/workbench\/.*\.map$/mu);
expect(listing.stdout).toMatch(/package\/dist\/workbench\/static\/js\/index\.[a-f0-9]{8}\.js$/mu);
expect(listing.stdout).toMatch(/package\/dist\/workbench\/static\/css\/index\.[a-f0-9]{8}\.css$/mu);
Expand Down
1 change: 0 additions & 1 deletion packages/agent-bundle/tests/license-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ it('ships the canonical Apache License 2.0 text and a NOTICE naming the copyrigh
expect(createHash('sha256').update(license).digest('hex')).toBe(canonicalApache2Sha256);
expect(notice.startsWith('agent-bundle\nCopyright 2026 ')).toBe(true);
expect(notice).toContain('THIRD_PARTY_NOTICES');
expect(notice).toContain('src/mcp/APP-RENDERER-LICENSE');
});

it('declares Apache-2.0 on every first-party workspace package', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ const expectedTree = `packages/
tests/playground-service.test.ts
tests/runtime-provider.test.ts
workbench/
src/mcp/runtime-app-bridge.ts
src/mcp/runtime-consent-dialog.tsx
src/mcp/runtime-consent-queue.ts
src/runtime-model.ts
tests/runtime-app-bridge.test.ts
tests/runtime-consent-dialog.test.ts
tests/runtime-consent-queue.test.ts
examples/
Expand Down Expand Up @@ -70,11 +68,9 @@ describe('rsc runtime topology script', () => {
'packages/agent-bundle/tests/normalization.test.ts',
'packages/agent-bundle/tests/playground-service.test.ts',
'packages/agent-bundle/tests/runtime-provider.test.ts',
'packages/workbench/src/mcp/runtime-app-bridge.ts',
'packages/workbench/src/mcp/runtime-consent-dialog.tsx',
'packages/workbench/src/mcp/runtime-consent-queue.ts',
'packages/workbench/src/runtime-model.ts',
'packages/workbench/tests/runtime-app-bridge.test.ts',
'packages/workbench/tests/runtime-consent-dialog.test.ts',
'packages/workbench/tests/runtime-consent-queue.test.ts',
'examples/rsc-agent-runtime/src/dev/provider.ts',
Expand Down
11 changes: 0 additions & 11 deletions packages/workbench/THIRD_PARTY_NOTICES
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
Agent Bundle workbench includes an MCP App renderer derived from the MCP
Inspector project's AppRenderer component:

MCP Inspector 2.2.0
https://github.com/modelcontextprotocol/inspector
commit 672f9f41c548487a468b9e7007d2f9de14da5a69
MIT License

The derived code is src/mcp/app-renderer.tsx. The MIT license text is in
src/mcp/APP-RENDERER-LICENSE.

Agent Bundle workbench bundles the xterm.js terminal emulator and its fit
addon for the Host sessions pane (src/sessions/terminal.tsx):

Expand Down
1 change: 0 additions & 1 deletion packages/workbench/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"dependencies": {
"@effect/atom-react": "4.0.0-rc.112",
"@modelcontextprotocol/client": "2.0.0",
"@modelcontextprotocol/ext-apps": "2.0.0",
"@xterm/addon-fit": "0.11.0",
"@xterm/xterm": "6.0.0",
"effect": "4.0.0-rc.112",
Expand Down
1 change: 0 additions & 1 deletion packages/workbench/rsbuild.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export const createWorkbenchConfig = (
overrideBrowserslist: ['chrome >= 120'],
copy: [
{ from: resolve(import.meta.dirname, 'THIRD_PARTY_NOTICES'), to: 'THIRD_PARTY_NOTICES', toType: 'file' },
{ from: resolve(sourceRoot, 'mcp', 'APP-RENDERER-LICENSE'), to: 'src/mcp/APP-RENDERER-LICENSE', toType: 'file' },
],
distPath: {
root: 'dist',
Expand Down
21 changes: 0 additions & 21 deletions packages/workbench/src/mcp/APP-RENDERER-LICENSE

This file was deleted.

Loading
Loading