Skip to main content
Glama
update_plane_issue_v2.js8.01 kB
import axios from 'axios'; import { get_plane_issue_id } from './get_plane_issue_id.js'; // Import the corrected handler // Removed duplicated getPlaneIssueId function async function updatePlaneIssue(server, args) { // Add server parameter try { // Parse parameters const params = args || {}; // Validate required parameters if (!params.project_id) { const errorText = JSON.stringify({ error: "Error: Project ID is required" }); return { content: [{ type: 'text', text: errorText }], isError: true }; } if (!params.issue_id) { const errorText = JSON.stringify({ error: "Error: Issue ID is required" }); return { content: [{ type: 'text', text: errorText }], isError: true }; } // Check if issue_id is a UUID, if not, try to resolve it let issue_id = params.issue_id; if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(issue_id)) { // Try to resolve the issue ID // Call the imported handler, passing the server instance and args const resolution_result = await get_plane_issue_id.handler(server, { issue_code: issue_id }); if (resolution_result.isError || !resolution_result.content || resolution_result.content.length === 0) { const errorDetail = resolution_result.content?.[0]?.text || 'Unknown error during resolution'; const errorText = JSON.stringify({ error: `Error: Could not resolve issue code ${issue_id} to a UUID. Details: ${errorDetail}` }); return { content: [{ type: 'text', text: errorText }], isError: true }; } try { const resolution_data = JSON.parse(resolution_result.content[0].text); if (resolution_data.issue_id && resolution_data.project_id) { params.issue_id = resolution_data.issue_id; // Update issue_id with the resolved UUID // Ensure project_id from params matches the resolved one, or use the resolved one if not provided initially if (!params.project_id || params.project_id === resolution_data.project_id) { params.project_id = resolution_data.project_id; } else { const errorText = JSON.stringify({ error: `Error: Resolved project ID (${resolution_data.project_id}) does not match provided project ID (${params.project_id}) for issue code ${issue_id}` }); return { content: [{ type: 'text', text: errorText }], isError: true }; } } else { const errorText = JSON.stringify({ error: `Error: Could not resolve issue code ${issue_id} to a UUID. Details: ${resolution_result.content[0].text}` }); return { content: [{ type: 'text', text: errorText }], isError: true }; } } catch (e) { const errorText = JSON.stringify({ error: `Error parsing resolution result for ${issue_id}. Details: ${resolution_result.content[0].text}` }); return { content: [{ type: 'text', text: errorText }], isError: true }; } } // Configuration const API_KEY = process.env.PLANE_API_KEY || "plane_api_614f7240a5df4177840558c34bddb668"; const BASE_URL = process.env.PLANE_BASE_URL || "http://192.168.50.90/api/v1"; const WORKSPACE_SLUG = process.env.PLANE_WORKSPACE_SLUG || "test-space"; const headers = { "X-API-Key": API_KEY, "Content-Type": "application/json" }; // Remove required fields from update data const update_data = { ...params }; delete update_data.project_id; delete update_data.issue_id; // If description is updated, also update HTML version if (update_data.description) { update_data.description_html = `<p>${update_data.description}</p>`; } if (Object.keys(update_data).length === 0) { const errorText = JSON.stringify({ error: "Error: No update parameters provided" }); return { content: [{ type: 'text', text: errorText }], isError: true }; } const url = `${BASE_URL}/workspaces/${WORKSPACE_SLUG}/projects/${params.project_id}/issues/${params.issue_id}/`; const response = await axios.patch(url, update_data, { headers }); if (response.status === 200) { const result = response.data; const changes = []; if (update_data.state_id) { changes.push("status changed"); } if (update_data.name) { changes.push("title updated"); } if (update_data.description) { changes.push("description updated"); } if (update_data.priority) { changes.push(`priority set to ${update_data.priority}`); } if (update_data.assignee_ids) { changes.push("assignees updated"); } const change_text = changes.length > 0 ? ` - ${changes.join(", ")}` : ""; const resultText = JSON.stringify({ message: `Issue updated: ${result.name} (#${result.sequence_id})${change_text}`, issue: result }, null, 2); return { content: [{ type: 'text', text: resultText }] }; } const errorText = JSON.stringify({ error: `Error: API request failed with status code ${response.status}` }); return { content: [{ type: 'text', text: errorText }], isError: true }; } catch (e) { if (axios.isAxiosError(e)) { const networkErrorText = JSON.stringify({ error: `Error: Network error - ${e.message}` }); return { content: [{ type: 'text', text: networkErrorText }], isError: true }; } const unexpectedErrorText = JSON.stringify({ error: `Error: Unexpected error - ${e.message}` }); return { content: [{ type: 'text', text: unexpectedErrorText }], isError: true }; } } export const updatePlaneIssueToolDefinition = { name: 'update_plane_issue_v2', description: 'Update an existing issue in a Plane project.', inputSchema: { type: 'object', properties: { project_id: { type: 'string', description: 'UUID of the project', }, issue_id: { type: 'string', description: 'UUID of the issue or issue code (e.g., PROJ-123)', }, state_id: { type: 'string', description: 'UUID of the state (Optional)', }, name: { type: 'string', description: 'New title (Optional)', }, description: { type: 'string', description: 'New description (Optional)', }, priority: { type: 'string', description: 'Issue priority (none, low, medium, high, urgent) (Optional)', }, assignee_ids: { type: 'array', items: { type: 'string' }, description: 'Array of user UUIDs (Optional)', }, label_ids: { type: 'array', items: { type: 'string' }, description: 'Array of label UUIDs (Optional)', }, start_date: { type: 'string', description: 'Start date in YYYY-MM-DD format (Optional)', }, target_date: { type: 'string', description: 'Target date in YYYY-MM-DD format (Optional)', }, }, required: ['project_id', 'issue_id'], }, }; export const update_plane_issue_v2 = { handler: updatePlaneIssue, definition: updatePlaneIssueToolDefinition }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oculairmedia/plane-projectmanagement_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server