// TypeScript demo: a read-only query, then a custom tool defined with Zod.
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
const PROJECT = new URL("../project", import.meta.url).pathname;
// --- Part 1: plain query over the sample project -------------------------------
console.log("=== Part 1: read-only query ===");
for await (const message of query({
prompt: "Which file in this project contains a hardcoded secret? Reply with the path and line only.",
options: { cwd: PROJECT, allowedTools: ["Read", "Glob", "Grep"], maxTurns: 6 },
})) {
if (message.type === "system" && message.subtype === "init") {
console.log(`init: model=${message.model} cli=${message.claude_code_version} session=${message.session_id}`);
} else if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "tool_use") console.log(`tool_use: ${block.name}`);
}
} else if (message.type === "result") {
console.log(`result: ${message.subtype} cost=$${message.total_cost_usd.toFixed(4)} turns=${message.num_turns}`);
if (message.subtype === "success") console.log(`answer: ${message.result}`);
}
}
// --- Part 2: a custom tool with a Zod schema -------------------------------------
console.log("\n=== Part 2: custom tool ===");
const convert = tool(
"convert_temperature",
"Convert a temperature between Celsius and Fahrenheit",
{
value: z.number().describe("The temperature value"),
from: z.enum(["C", "F"]).describe("Unit of the input value"),
},
async ({ value, from }) => {
const result = from === "C" ? (value * 9) / 5 + 32 : ((value - 32) * 5) / 9;
const to = from === "C" ? "F" : "C";
return { content: [{ type: "text", text: `${value}°${from} = ${result.toFixed(1)}°${to}` }] };
},
{ annotations: { readOnlyHint: true } },
);
const server = createSdkMcpServer({ name: "temps", version: "1.0.0", tools: [convert] });
for await (const message of query({
prompt: "What is 100°F in Celsius and 37°C in Fahrenheit? Use the tool for both.",
options: {
cwd: PROJECT,
mcpServers: { temps: server },
allowedTools: ["mcp__temps__convert_temperature"],
tools: [], // no built-in tools
maxTurns: 6,
},
})) {
if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "tool_use") console.log(`tool_use: ${block.name}(${JSON.stringify(block.input)})`);
}
} else if (message.type === "user" && Array.isArray(message.message.content)) {
for (const block of message.message.content) {
if (block.type === "tool_result") console.log(`tool_result: ${JSON.stringify(block.content)}`);
}
} else if (message.type === "result" && message.subtype === "success") {
console.log(`answer: ${message.result}`);
}
}
66 lines · Back to the folder