Mastra MCP client: connect an agent to Sume's hosted MCP
Connect a Mastra agent to Sume's hosted MCP server with MCPClient: an API-key header in requestInit, a tool allow-list, and approval for paid calls.

To connect a Mastra agent to Sume's tools, create an MCPClient with a sume server at new URL("https://mcp.sume.com/mcp"), put your Sume API key in requestInit.headers as Authorization: Bearer, set requireToolApproval so paid calls wait for a person, and give the agent only the tools it needs from await mcp.listTools().
The Mastra facts come from its MCP guide, MCPClient reference, and human-in-the-loop pages; the Sume facts come from OAuth and API keys, MCP tools and gates, and Jobs and results, all read on 2026-09-27. Sume has no Mastra package or plugin; MCPClient from @mastra/mcp is Mastra's own client. Sume's basics page says hosted MCP still works but is not part of the primary path today. For a REST tool instead, see Vercel AI SDK: generate video with a Sume API tool call.
How do I configure MCPClient for Sume?
Install @mastra/mcp@latest. A server defined by a url uses the Streamable HTTP transport, and requestInit is the fetch configuration for its requests. Sume takes the key as Authorization: Bearer or x-api-key; send one of the two, from an environment variable, as Mastra's docs advise for API keys:
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
export const mcp = new MCPClient({
id: "sume-mcp",
servers: {
sume: {
url: new URL("https://mcp.sume.com/mcp"),
requestInit: { headers: { Authorization: `Bearer ${process.env.SUME_API_KEY}` } },
requireToolApproval: ({ toolName, args }) =>
toolName === "generate_video" && args.dry_run !== true,
},
},
});
const keep = ["tools_schema", "balance_get", "generate_video", "jobs_wait", "jobs_result"];
const tools = Object.fromEntries(
Object.entries(await mcp.listTools()).filter(([name]) => keep.some((t) => name === `sume_${t}`)),
);
export const producer = new Agent({
id: "producer",
name: "Video producer",
instructions: "Preview generate_video with dry_run: true first. Wait with jobs_wait; never resubmit.",
model: "openai/gpt-5-mini",
tools,
});Which tool names will the agent see?
listTools() returns the tools of every configured server, namespaced as serverName_toolName, so Sume's generate_video becomes sume_generate_video. An API-key session on Sume sees write and paid tools, so the example keeps five; the Sume MCP tools list sorts the rest by whether they read, write, or spend.
| Name in Mastra | Sume group | Approval |
|---|---|---|
sume_tools_schema | Discovery | No |
sume_balance_get | Account and catalog | No |
sume_generate_video | Paid; needs idempotency_key | Yes, unless dry_run is true |
sume_jobs_wait, sume_jobs_result | Jobs, read | No |
sume_jobs_cancel | Jobs, write | Left out |
How do paid Sume calls wait for approval?
On a server definition, requireToolApproval takes true or a function that receives the tool name, the arguments the model passed, the request context, and any annotations the server advertises. Mastra lists cost-heavy calls to third-party APIs, where you want to verify arguments first, as a reason for human-in-the-loop.
When a call needs approval, the stream emits a tool-call-approval chunk with toolCallId, toolName, and args. Continue with agent.approveToolCall({ runId }) or agent.declineToolCall({ runId }). With generate(), the result comes back with finishReason: 'suspended', and approveToolCallGenerate({ runId, toolCallId }) continues it.
- Approval uses snapshots, so configure a storage provider on your Mastra instance or you'll see a "snapshot not found" error.
- Decide on tool names, not annotations: Mastra says to treat annotations from servers you don't control as untrusted hints.
- Sume's own gates still apply:
dry_run=truepreviews admission and cost without submitting the job, andmax_spend_usdcaps a call only when you pass it. Estimate AI video cost before you run covers the preview.
Is MCPClient's timeout long enough for jobs_wait?
Yes, with a few seconds to spare. The client-level timeout defaults to 60000 milliseconds, and a server-level timeout overrides it. Sume's jobs_wait holds one call for at most 55 seconds, or 50 when timeout_seconds is omitted, so keep the timeout at or above the default.
- On
wait_slice_expired, calljobs_waitagain with the same ids; never resubmit the paid create. A524,522,523, or525onjobs_waitis a transport failure, not a job outcome. - By default (
onToolError: 'throw'), an in-band tool error raises aMastraErrorcarrying the server's error text, so the failure reaches the model.
Should I use listTools or listToolsets?
Use listTools() in the Agent constructor when one Sume key serves every request: its credentials are shared by all requests. When each of your users has their own Sume key, create a client per request, pass await client.listToolsets() to generate() or stream(), and call disconnect() when the response is done. listToolsets() names tools serverName.toolName.
Sources
Related posts
More in Integrations
- n8n AI video workflow: resume a Wait node on a Sume webhook
Start a Sume Format run from an n8n HTTP Request node, pass the Wait node's resume URL as webhook_url, then read the finished run with your key.
- n8n Google Sheets AI avatar video: one Sume video per row
Read rows with n8n's Google Sheets node, submit one Sume talking-avatar job per row, poll in a capped loop, and write each video URL to the sheet.
- n8n MCP Client Tool with Sume: setup and the SSE caveat
n8n labels the MCP Client Tool field SSE Endpoint; Sume documents streamable HTTP. Set it up for Sume, test the connection, and gate paid calls.
- OpenAI Agents SDK MCP server: Sume and the 5-second timeout
Connect the OpenAI Agents SDK to Sume's hosted MCP server with an API key, and raise the 5-second client timeouts above jobs_wait's 55 seconds.
Written by Sume