mcp-planes-server
Version:
Plane API client and server
149 lines (148 loc) • 6.41 kB
JavaScript
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}`);
}
},
};
}