The MCP SDK v1.29.0 changed server.tool() to require Zod schemas (raw shapes) instead of plain JSON Schema objects. The old format triggered "expected a Zod schema or ToolAnnotations" errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
117 lines
2.9 KiB
TypeScript
117 lines
2.9 KiB
TypeScript
import { z } from "zod";
|
|
import type { db as prodDb } from "../../../db/index.ts";
|
|
import {
|
|
createSetup,
|
|
getAllSetups,
|
|
getSetupWithItems,
|
|
syncSetupItems,
|
|
updateSetup,
|
|
} from "../../services/setup.service.ts";
|
|
|
|
type Db = typeof prodDb;
|
|
|
|
interface ToolResult {
|
|
content: Array<{ type: "text"; text: string }>;
|
|
}
|
|
|
|
function textResult(data: unknown): ToolResult {
|
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
}
|
|
|
|
function errorResult(message: string): ToolResult {
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
};
|
|
}
|
|
|
|
export const setupToolDefinitions = [
|
|
{
|
|
name: "list_setups",
|
|
description:
|
|
"List all gear setups with item counts and weight/cost totals.",
|
|
inputSchema: {},
|
|
},
|
|
{
|
|
name: "get_setup",
|
|
description: "Get a setup with all its items and details.",
|
|
inputSchema: {
|
|
id: z.number().describe("Setup ID"),
|
|
},
|
|
},
|
|
{
|
|
name: "create_setup",
|
|
description: "Create a new gear setup (e.g. 'Bikepacking weekend').",
|
|
inputSchema: {
|
|
name: z.string().describe("Setup name"),
|
|
},
|
|
},
|
|
{
|
|
name: "update_setup",
|
|
description:
|
|
"Update a setup's name and/or replace its item list. Pass itemIds to set exactly which items belong to this setup.",
|
|
inputSchema: {
|
|
id: z.number().describe("Setup ID"),
|
|
name: z.string().optional().describe("New setup name"),
|
|
itemIds: z
|
|
.array(z.number())
|
|
.optional()
|
|
.describe("Array of item IDs to include in the setup"),
|
|
},
|
|
},
|
|
];
|
|
|
|
export function registerSetupTools(db: Db) {
|
|
return {
|
|
list_setups: async (): Promise<ToolResult> => {
|
|
try {
|
|
const setupList = getAllSetups(db);
|
|
return textResult(setupList);
|
|
} catch (err) {
|
|
return errorResult((err as Error).message);
|
|
}
|
|
},
|
|
|
|
get_setup: async (args: { id: number }): Promise<ToolResult> => {
|
|
try {
|
|
const setup = getSetupWithItems(db, args.id);
|
|
if (!setup) return errorResult(`Setup ${args.id} not found`);
|
|
return textResult(setup);
|
|
} catch (err) {
|
|
return errorResult((err as Error).message);
|
|
}
|
|
},
|
|
|
|
create_setup: async (args: { name: string }): Promise<ToolResult> => {
|
|
try {
|
|
const setup = createSetup(db, args);
|
|
return textResult(setup);
|
|
} catch (err) {
|
|
return errorResult((err as Error).message);
|
|
}
|
|
},
|
|
|
|
update_setup: async (args: {
|
|
id: number;
|
|
name?: string;
|
|
itemIds?: number[];
|
|
}): Promise<ToolResult> => {
|
|
try {
|
|
let setup = null;
|
|
if (args.name) {
|
|
setup = updateSetup(db, args.id, { name: args.name });
|
|
if (!setup) return errorResult(`Setup ${args.id} not found`);
|
|
}
|
|
if (args.itemIds) {
|
|
syncSetupItems(db, args.id, args.itemIds);
|
|
}
|
|
// Return updated setup with items
|
|
const result = getSetupWithItems(db, args.id);
|
|
if (!result) return errorResult(`Setup ${args.id} not found`);
|
|
return textResult(result);
|
|
} catch (err) {
|
|
return errorResult((err as Error).message);
|
|
}
|
|
},
|
|
};
|
|
}
|