---
title: "How do I call Ballet playbooks from the Vercel AI SDK?"
description: "TL;DR: Use the AI SDK's MCP client to import Ballet's tools, or define a single tool() that calls the execute endpoint. Point the MCP client at https://app.ballet.dev/mcp with an Authorization: Bearer header, await mcpClient.tools(), and pass them to generateText."
canonical_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-the-vercel-ai-sdk-f2WDKmGWk5"
md_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-the-vercel-ai-sdk-f2WDKmGWk5.md"
---
# How do I call Ballet playbooks from the Vercel AI SDK?

**TL;DR:** Use the AI SDK's MCP client to import Ballet's tools, or define a single `tool()` that calls the execute endpoint. Point the MCP client at `https://app.ballet.dev/mcp` with an `Authorization: Bearer` header, await `mcpClient.tools()`, and pass them to `generateText`.

## Who this is for

TypeScript developers building agents with the Vercel AI SDK.

## Option A: Import Ballet's tools over MCP

Configure the AI SDK's MCP client with the HTTP transport and your token. The returned tools (`run_playbook`, `get_run`, `list_playbooks`, …) drop straight into `generateText` or `streamText`.

```ts
import { openai } from "@ai-sdk/openai";
import { createMCPClient } from "@ai-sdk/mcp";
import { generateText, stepCountIs } from "ai";

const mcpClient = await createMCPClient({
  transport: {
    type: "http",
    url: "https://app.ballet.dev/mcp",
    headers: { Authorization: `Bearer ${process.env.BALLET_API_TOKEN}` },
  },
});

try {
  const tools = await mcpClient.tools();

  const { text } = await generateText({
    model: openai("gpt-4o"),
    tools,
    stopWhen: stepCountIs(10),
    prompt: "Run the lead-enrichment playbook for cus_123 and summarize the result.",
  });

  console.log(text);
} finally {
  await mcpClient.close();
}
```

For interactive apps you can supply an `authProvider` instead of a static header to use Ballet's browser-based OAuth — see [the MCP endpoint](/articles/how-do-i-connect-to-ballets-mcp-endpoint-1ydPKBzHZm).

## Option B: Define one playbook as a tool

When you only need to expose a single playbook, define a `tool()` that calls the REST execute endpoint and returns the run output.

```ts
import { tool } from "ai";
import { z } from "zod";

export const runPlaybook = tool({
  description: "Run the customer onboarding playbook in Ballet.",
  inputSchema: z.object({ customerId: z.string() }),
  execute: async ({ customerId }) => {
    const res = await fetch(
      `https://app.ballet.dev/api/playbooks/${process.env.BALLET_PLAYBOOK_ID}/execute`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.BALLET_API_TOKEN}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ input: { customerId } }),
      },
    );

    let result;
    for (const frame of (await res.text()).split("\n\n")) {
      const line = frame.split("\n").find((l) => l.startsWith("data:"));
      if (!line) continue;
      const event = JSON.parse(line.slice(5).trim());
      if (event.type === "run_stop") result = event.run;
    }
    return { success: result?.success, output: result?.output };
  },
});
```

See [Run playbooks over the REST API](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm) for the streaming details.

## Which option should I use?

- **MCP** — let the model discover and call any playbook in your workspace.
- **REST tool** — expose exactly one playbook with a precise input schema.

## Related articles

- [How do I use Ballet playbooks in an agent framework?](/articles/how-do-i-use-ballet-playbooks-in-an-agent-framework-q3PWTx18lY)
- [The MCP endpoint](/articles/how-do-i-connect-to-ballets-mcp-endpoint-1ydPKBzHZm)
- [Run playbooks over the REST API](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm)
