AI SDK MCP tools(): explicit Zod schemas for Sume's jobs_wait
Pass explicit Zod schemas to mcpClient.tools() so your app exposes only the Sume tools it needs, with typed job ids and a bounded wait_for.

The AI SDK's MCP client can discover every tool a server offers, or you can name the ones you want. The AI SDK MCP tools page says schema discovery uses mcpClient.tools(), and that explicit Zod schemas pull only the named tools and give TypeScript types, read 2026-10-03. A tool with no arguments uses an empty object schema. For a Sume integration that only needs to wait on and read jobs, that is a smaller, safer surface than every create tool.
Schemas for the read-side tools
Sume's tools and gates page says jobs_wait takes job_ids (1 to 20) and wait_for of all or any. The schema below encodes those limits. Only the fields the docs name are included; if the server accepts more, the AI SDK page does not say how extra fields are handled, so check the tool's schema with tools_schema.
The transport shape comes from the AI SDK page: type: 'http', a url, and headers. It recommends HTTP for production.
import { createMCPClient } from "@ai-sdk/mcp";
import { z } from "zod";
const client = await createMCPClient({
transport: {
type: "http",
url: "https://mcp.sume.com/mcp",
headers: { Authorization: `Bearer ${process.env.SUME_API_KEY}` },
},
});
try {
const tools = await client.tools({
schemas: {
jobs_wait: {
inputSchema: z.object({
job_ids: z.array(z.string()).min(1).max(20),
wait_for: z.enum(["all", "any"]).optional(),
}),
},
},
});
console.log(Object.keys(tools));
} finally {
await client.close();
}Why restrict the tool list
Sume gates paid and write tools with idempotency_key, and under OAuth with the mcp:write scope, but a model that never sees the create tool cannot call it. Restrict first, gate second.
| Approach | Tools exposed | Trade-off |
|---|---|---|
tools() with no schemas | Everything the server lists | Includes paid create tools; the model may call them |
tools({ schemas }) | Only the named tools | You maintain the schemas; types are checked |
| Zero-argument tool | Empty z.object({}) | Needed for tools that take no input |
Close the client
The page says to close the client with onEnd for streams or try/finally otherwise, which the snippet does. A leaked client keeps a connection open. For waits longer than a single hold, loop in your own code on wait_slice_expired using the same ids; never resubmit a paid create.
Sources
Related posts
More in Developers
- AI video defaults on Sume: 768p, 480p, 720p and 8 seconds explained
Recast defaults to 768p, Genjutsu to 480p, Gemini Omni Flash and sume/auto to 720p and 8 s. Which defaults change price, and the one place fal differs.
- AI video models with no aspect_ratio option: Recast, Genjutsu, Grok
Three Sume video rows reject aspect_ratio: H3 Max Recast, Higgsfield Genjutsu and Grok Imagine Video 1.5. What sets the output frame instead, and what to send.
- AI video person swap rejects long takes: find shots over 15 s
H3 Max Recast on Sume needs 5 to 30 seconds with no single shot over 15. Find the long takes with ffmpeg scene detection, then cut them before you pay.
- AI voice reads Spanish with an English accent: two causes to check
Spanish read with an English accent usually means the language field was omitted or the voice is tagged for another language. How Sume's TTS 409 works.
Written by Sume