Core Concepts

Views

Edit a View, see it reload in preview, and call backing tools.

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

Edit view.tsx

get-forecast/view.tsx
import { useApp } from "bitmcp/react";

export default function Forecast() {
  const { result, callTool } = useApp();
  if (!result) return null;
  return (
    <div className="p-4 text-foreground">
      <h1>{result.city}</h1>
      <p className="text-muted">{result.summary}</p>
      <button
        type="button"
        onClick={() => callTool("get-forecast.refresh", { city: result.city })}
      >
        Refresh
      </button>
    </div>
  );
}

See the hash reload

pnpm dev

Change the View and save. The preview reloads the iframe when the View hash changes. Seed input with Preview fixtures.

Show the forecast card for San Francisco
Reply to Claude…

Troubleshooting

  • Blank iframe — Confirm the tool returned structured content matching your output schema.
  • Fetch blocked in View — Add the API domain to connect on the sibling tool. See Tools.
  • Styles missing — Use Tailwind className utilities. The compiler inlines CSS per View.

Reference

ui:// resources

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

  • URI shape: ui://tools/<name>/<hash>
  • Content-addressed hash of compiled HTML (scripts and CSS inlined)
  • Cacheable with ttlMs and cacheScope: public

useApp()

get-forecast/view.tsx
const { result, callTool, app, isConnected, error } = useApp();

File-based tools generate .bitmcp/views.d.ts so result is inferred from the sibling tool.

FieldDescription
resultstructuredContent from the host, or from callTool
callTool(name, args?)Calls a backing tool through the host
appOfficial Apps client instance
isConnectedConnection state
errorConnection error if any

Views never call your server directly. callTool goes through the host as a stateless tools/call.

Styling

Every View is compiled with Tailwind v4. Theme tokens: bg-background, text-foreground, text-muted, border-border, font-sans. Add src/views.css only for extra @theme tokens or @source paths.

Escape hatches

get-forecast/view.tsx
import { useMcpApp, useHostStyles } from "bitmcp/react";

Use only when you need direct access to the official client. The happy path is useApp().

Build boundaries

  • Do not import tool.ts from view.tsx
  • Do not import Node builtins or secrets in Views
  • fetch in a View requires a sibling connect allowlist