Core Concepts

Tools

Define a tool, return data, and test it in the preview.

A tool is a server function exposed to the model through MCP.

Create a tool folder

Add a tool folder under src/tools/ (see Project structure). Each folder needs tool.ts; add view.tsx beside it for a View.

Define the tool

get-forecast/tool.ts
import { z } from "zod";
import { defineTool } from "bitmcp";

export default defineTool({
  description: "Get a forecast and show an interactive chart",
  input: z.object({ city: z.string() }),
  output: z.object({
    city: z.string(),
    summary: z.string(),
    points: z.array(z.object({ t: z.string(), temp: z.number() })),
  }),
  async execute({ city }) {
    return {
      city,
      summary: `Mild in ${city}`,
      points: [
        { t: "Mon", temp: 68 },
        { t: "Tue", temp: 72 },
        { t: "Wed", temp: 70 },
      ],
    };
  },
});

For a read-only list tool, the same pattern applies:

get-posts/tool.ts
import { z } from "zod";
import { defineTool } from "bitmcp";

export default defineTool({
  description: "Get recent blog posts",
  input: z.object({ tag: z.string().optional() }),
  output: z.object({
    posts: z.array(
      z.object({
        id: z.string(),
        title: z.string(),
        excerpt: z.string(),
      }),
    ),
  }),
  async execute({ tag }) {
    const posts = await fetchPosts(tag);
    return { posts };
  },
});

Return data

Returning an object produces structuredContent for the View and text for every host.

Custom text:

get-forecast/tool.ts
import { result } from "bitmcp";

return result(data, `Forecast for ${city}: ${data.summary}`);

Test in preview

pnpm dev

Call the tool from the local preview or an MCP client. Confirm you receive text and structured content.

Reference

Schemas

  • input validates tool arguments (Zod or Standard Schema)
  • output validates the return value and types the View result

CSP allowlists

Default CSP is deny-all for iframe network access.

  • connect — connect-src allowlist for fetch from the View
  • resources — asset src allowlist for CDN scripts or styles
get-forecast/tool.ts
defineTool({
  connect: ["https://api.example.com"],
  // ...
});

Visibility and scopes

Defaults to ["model", "app"]. Use Actions for app-only tools.

requiredScopes gates a tool behind OAuth scopes. See Supabase and other auth pages.

Rules

  • execute runs on the server only
  • Text is always produced
  • Presence of view.tsx attaches UI. Do not set resourceUri manually
  • execute must not return undefined
  • confirm sets destructiveHint: true unless you override annotations. See Confirmations

defineTool options

FieldDescription
descriptionRequired. Shown in tools/list
inputArgument schema
outputReturn schema and View typing
executeServer handler
connectCSP connect-src allowlist
resourcesCSP asset allowlist
visibility["model", "app"] default
requiredScopesOAuth scopes required to call the tool
annotationsMCP tool hints (readOnlyHint, destructiveHint, etc.)
confirmMRTR gate before execute. See Confirmations

ToolContext

FieldDescription
ask(schema, message?)MRTR continuation inside execute
inputRequired(spec)Raw MRTR escape hatch
inputResponsesAnswers from a prior ask
handle()Mint opaque handle id
userAuthenticated user when OAuth is enabled
requestIncoming HTTP request or stdio envelope

Result helpers

result(data, text): Result<T>
isResult(value): boolean

MRTR flow: Connecting.