105 lines
2.5 KiB
JavaScript
105 lines
2.5 KiB
JavaScript
#!/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());
|