#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/server"; import { serveStdio } from "@modelcontextprotocol/server/stdio"; import * as z from "zod/v4"; import { applyCanvasOperation, getCanvas, getCurrentUser, listCanvases, } from "./api-client.mjs"; function toolResult(payload) { return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }], structuredContent: payload, }; } function toolError(error) { return { isError: true, content: [ { type: "text", text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), status: Number(error?.status) || undefined, details: error?.payload || undefined, }), }, ], }; } function register(server, name, definition, handler) { server.registerTool(name, definition, async (input) => { try { return toolResult(await handler(input)); } catch (error) { return toolError(error); } }); } function buildServer() { const server = new McpServer({ name: "yedir-canvas", version: "0.1.0", }); register( server, "yedir_get_current_user", { description: "Verify the configured Yedir Access Key and return its user and scopes.", inputSchema: z.object({}), }, () => getCurrentUser() ); register( server, "yedir_list_canvases", { description: "List canvases owned by the authenticated user.", inputSchema: z.object({ workspaceType: z.enum(["canvas", "agent", "video"]).default("canvas"), limit: z.number().int().min(1).max(50).default(24), }), }, (input) => listCanvases(input) ); register( server, "yedir_get_canvas", { description: "Read one canvas including its current revision, nodes, edges, and viewport.", inputSchema: z.object({ canvasId: z.string().uuid() }), }, ({ canvasId }) => getCanvas(canvasId) ); register( server, "yedir_apply_canvas_operation", { description: "Apply one versioned semantic CanvasOperationPlan. Moving, deleting, or replacing content requires confirmed=true after explicit user confirmation.", inputSchema: z.object({ canvasId: z.string().uuid(), operationPlan: z.record(z.string(), z.unknown()), }), }, ({ canvasId, operationPlan }) => applyCanvasOperation(canvasId, operationPlan) ); return server; } await serveStdio(() => buildServer());