UNPKG

mcp-planes-server

Version:

Plane API client and server

149 lines (148 loc) 6.41 kB
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; import { client } from "../shared.js"; export function getResourceHandlers() { return { listResources: async () => { return { resources: [ { uri: "planes://projects", name: "Projects in Plane", mimeType: "application/json", description: "Projects in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/issues", name: "Issues in Plane", mimeType: "application/json", description: "Issues in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/labels", name: "Labels in Plane", mimeType: "application/json", description: "Labels in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/comments", name: "Comments in Plane", mimeType: "application/json", description: "Comments in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/states", name: "States in Plane", mimeType: "application/json", description: "States in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/members", name: "Members in Plane", mimeType: "application/json", description: "Members in Plane", }, { uri: "planes://33bd0d87-ebef-4f97-85d0-3b89bf39767e/cycles", name: "Cycles in Plane", mimeType: "application/json", description: "Cycles in Plane", } ], }; }, readResource: async (request) => { const uri = request.params.uri; const parts = uri.replace("planes://", "").split("/"); // 解析资源 URI const isProjects = parts[0] === "projects"; if ((isProjects) && parts.length === 1) { const fn = 'getProjects'; const { results } = await client[fn](); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(results, null, 2), }, ], }; } if (parts.length < 2) { throw new McpError(ErrorCode.InvalidRequest, "Invalid resource URI format"); } const [projectId, resourceType] = parts; try { switch (resourceType) { case "issues": { const issues = await client.getIssues({ projectId }); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(issues, null, 2), }, ], }; } case "labels": { const labels = await client.getLabels({ projectId }); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(labels, null, 2), }, ], }; } case "states": { const states = await client.getStates({ projectId }); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(states, null, 2), }, ], }; } case "members": { const members = await client.getMembers({ projectId }); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(members, null, 2), }, ], }; } case "cycles": { const cycles = await client.getCycles({ projectId }); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(cycles, null, 2), }, ], }; } default: throw new McpError(ErrorCode.InvalidRequest, `Unsupported resource type: ${resourceType}`); } } catch (error) { if (error instanceof McpError) throw error; throw new McpError(ErrorCode.InternalError, `Failed to read resource: ${error}`); } }, }; }