---
title: "How do I call Ballet playbooks from Mastra?"
description: "TL;DR: Use Mastra's MCPClient to connect to Ballet's MCP endpoint, or define a createTool that calls the execute endpoint. Configure a server entry with url: new URL(\"https://app.ballet.dev/mcp\") and an Authorization header, then pass await mcp.getTools() to an Agent."
canonical_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-mastra-mUk4Q7k4Lw"
md_url: "https://docs.ballet.dev/articles/how-do-i-call-ballet-playbooks-from-mastra-mUk4Q7k4Lw.md"
---
# How do I call Ballet playbooks from Mastra?

**TL;DR:** Use Mastra's `MCPClient` to connect to Ballet's MCP endpoint, or define a `createTool` that calls the execute endpoint. Configure a server entry with `url: new URL("https://app.ballet.dev/mcp")` and an `Authorization` header, then pass `await mcp.getTools()` to an `Agent`.

## Who this is for

TypeScript developers building agents with Mastra.

## Option A: Connect over MCP

Install `@mastra/mcp`, register Ballet as a server (Mastra tries Streamable HTTP first), and hand the tools to an `Agent`.

```ts
import { MCPClient } from "@mastra/mcp";
import { Agent } from "@mastra/core/agent";
import { openai } from "@ai-sdk/openai";

const mcp = new MCPClient({
  servers: {
    ballet: {
      url: new URL("https://app.ballet.dev/mcp"),
      requestInit: {
        headers: { Authorization: `Bearer ${process.env.BALLET_API_TOKEN}` },
      },
    },
  },
});

const agent = new Agent({
  name: "ops-agent",
  instructions: "You run Ballet playbooks to complete operational tasks.",
  model: openai("gpt-4o"),
  tools: await mcp.getTools(),
});

const result = await agent.generate(
  "Run the lead-enrichment playbook for cus_123 and summarize the result.",
);
console.log(result.text);
```

For per-request auth (for example a rotating token), use the `fetch` option on the server entry instead of `requestInit`.

## Option B: Define one playbook as a tool

To expose a single playbook, wrap the REST execute endpoint with `createTool`.

```ts
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const runOnboarding = createTool({
  id: "run-onboarding",
  description: "Run the customer onboarding playbook in Ballet.",
  inputSchema: z.object({ customerId: z.string() }),
  execute: async ({ context }) => {
    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: context.customerId } }),
      },
    );

    let run;
    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") run = event.run;
    }
    return { success: run?.success, output: run?.output };
  },
});
```

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

## Which option should I use?

- **MCP** — expose every playbook to the agent and let Mastra manage the connection.
- **REST tool** — expose one playbook with a precise 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)
