Skip to content

defineRscAgentBundle: no way to declare MCP Apps (mcp.servers[].apps) in the RSC element tree #42

Description

@ScriptedAlchemy

Package: @agent-bundle/rsc-runtime (defineRscAgentBundle, <McpServer>), observed at pkg.pr.new preview 0.0.0-preview-4e546516 (main @ 4e546516).

What we tried

We're porting a 42-tool MCP plugin (movie-library) with one MCP App widget (ui://movie-library/widget.html) onto the RSC entry point. The config layer already fully supports apps — AgentBundleMcpApp / AgentBundleMcpServer.apps in agent-bundle/config, dedicated validation, compilation into self-contained resources served via import apps from 'agent-bundle/mcp-apps' — so we expected to declare the widget next to the server that owns it:

import { AgentBundle, McpServer, defineRscAgentBundle } from '@agent-bundle/rsc-runtime/plugin';

export const application = defineRscAgentBundle(
  <AgentBundle name="movie-library" version="1.0.0" targets={['portable', 'claude', 'codex']}>
    <McpServer
      name="movie-library"
      entry="./src/mcp-server.ts"
      // ✗ no such prop — McpServerProps is only { entry, name, targets? }
      apps={{
        widget: {
          entry: './views/widget.ts',
          template: './views/widget.html',
          resourceUri: 'ui://movie-library/widget.html',
        },
      }}
    />
  </AgentBundle>,
);

There is no <App>/view child element either: defineRscAgentBundle lowers rsc-agent-mcp-server to { entry, targets } only (extra props are a type error and ignored by the lowering regardless), and any unrecognized child of <AgentBundle> throws AgentBundle contains unsupported child ….

Why it matters

Plugins with widgets are exactly the ones the MCP Apps pipeline exists for, and for them defineRscAgentBundle stops being the single source of truth: application.config is incomplete, so anything consuming the application object directly (createRscMcpServer, tests, tooling) has no knowledge of the app or its resource URI.

Current workaround

agent-bundle.config.ts spreads the generated config and splices the app in config-side:

import { movieLibraryApplication } from './src/application.tsx';

const config = movieLibraryApplication.config;

export default {
  ...config,
  mcp: {
    servers: {
      'movie-library': {
        ...config.mcp!.servers['movie-library'],
        apps: {
          widget: {
            entry: './views/widget.ts',
            template: './views/widget.html',
            resourceUri: 'ui://movie-library/widget.html',
          },
        },
      },
    },
  },
};

Build and validate are happy with this, but the RSC application object still doesn't know the widget exists — our server factory has to accept the compiled widget resource as an explicit parameter instead of reading it off the application. Workable; not blocking.

Suggested fix direction

Either (or both):

  • a first-class child element, e.g. <App name="widget" entry="./views/widget.ts" template="./views/widget.html" resourceUri="ui://movie-library/widget.html" /> inside <McpServer>, lowered into AgentBundleMcpServer.apps (config-side validation already exists), or
  • an apps prop on McpServerProps as a typed config passthrough.

Relevant code: packages/rsc-runtime/src/plugin-elements.ts (McpServerProps), packages/rsc-runtime/src/plugin-definition.ts (rsc-agent-mcp-server lowering), packages/agent-bundle/src/core/types.ts (AgentBundleMcpApp).


Related: #43, #44 — sibling framework gaps surfaced by the same consumer port (movie-library on preview 4e546516).

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

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions