Files
GearBox/src/server/mcp/tools/setups.ts
Jean-Luc Makiola 4f434f39bf
All checks were successful
CI / ci (push) Successful in 33s
fix: replace @/ path alias with relative imports in MCP server
The @/ alias resolves via tsconfig but not in production where
Bun runs server files directly. Use relative paths instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:22:23 +02:00

132 lines
3.2 KiB
TypeScript

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: {
type: "object" as const,
properties: {},
},
},
{
name: "get_setup",
description: "Get a setup with all its items and details.",
inputSchema: {
type: "object" as const,
properties: {
id: { type: "number", description: "Setup ID" },
},
required: ["id"],
},
},
{
name: "create_setup",
description: "Create a new gear setup (e.g. 'Bikepacking weekend').",
inputSchema: {
type: "object" as const,
properties: {
name: { type: "string", description: "Setup name" },
},
required: ["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: {
type: "object" as const,
properties: {
id: { type: "number", description: "Setup ID" },
name: { type: "string", description: "New setup name" },
itemIds: {
type: "array",
items: { type: "number" },
description: "Array of item IDs to include in the setup",
},
},
required: ["id"],
},
},
];
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);
}
},
};
}