Views

Hashed ui:// HTML, the compiler shell, useApp(), and callTool().

A View is a React component compiled into a predeclared HTML resource.

import { useApp } from "bitmcp/react";

export default function Forecast() {
  const { result, callTool } = useApp();
  if (!result) return null;
  return (
    <div>
      <h1>{result.city}</h1>
      <button
        type="button"
        onClick={() => callTool("forecast.refresh", { city: result.city })}
      >
        Refresh
      </button>
    </div>
  );
}

ui:// resources

The compiler bundles view.tsx into one HTML document with MIME type text/html;profile=mcp-app.

  • URI shape: ui://tools/<name>/<hash>
  • Content-addressed: the hash is the compiled HTML (scripts and CSS inlined), not the TSX source
  • Cacheable with ttlMs and cacheScope: public

HTML shell

The compiler injects:

  • Official Apps useApp({ appInfo })
  • Host theme via useHostStyles
  • Typed result from the sibling tool

Authors never pass appInfo or call useHostStyles on the happy path.

Data flow

  1. Host calls the tool
  2. structuredContent arrives via ontoolresult
  3. Host loads the hashed HTML in a sandbox iframe
  4. View reads result from useApp()

callTool

Views never call your server directly. callTool goes through the host, which issues a new stateless tools/call.

Network from the iframe is CSP-gated. Tool calls are not.

Build boundaries

  • Do not import tool.ts from view.tsx
  • Do not import Node builtins or secrets in Views