Skip to main content
Glama

create-issue

Create new issues in Plane projects by specifying title, description, priority, assignees, and project details for effective task management.

Instructions

Create a new issue in a project

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_idYesID of the project where the issue should be created
nameYesTitle of the issue
description_htmlNoHTML description of the issue (required by Plane API)
priorityNoPriority of the issue (urgent, high, medium, low, none)
state_idNoID of the state for this issue (optional)
assigneesNoArray of user IDs to assign to this issue (optional)

Implementation Reference

  • Handler for the 'create-issue' tool: validates input, normalizes assignees array, calls Plane API to POST new issue to /projects/{project_id}/issues/, returns JSON response.
    case "create-issue": {
      if (!args || typeof args.project_id !== "string") {
        throw new Error("Project ID is required");
      }
      const { project_id, ...issueData } = args;
    
      // Ensure assignees is properly formatted as an array
      if (issueData.assignees) {
        // Special case: detect if entire issue is nested in assignees
        if (
          typeof issueData.assignees === "object" &&
          !Array.isArray(issueData.assignees) &&
          (issueData.assignees as Record<string, any>).project_id &&
          (issueData.assignees as Record<string, any>).name
        ) {
          // Issue is nested inside assignees, remove it completely
          delete issueData.assignees;
        } else if (!Array.isArray(issueData.assignees)) {
          if (typeof issueData.assignees === "string") {
            // Convert single string to array
            issueData.assignees = [issueData.assignees];
          } else if (typeof issueData.assignees === "object") {
            // Convert object to array of values
            issueData.assignees = Object.values(issueData.assignees);
          } else {
            // Remove invalid assignees
            delete issueData.assignees;
          }
        }
      }
    
      const issue = await callPlaneAPI(
        `/projects/${project_id}/issues/`,
        "POST",
        issueData
      );
      return {
        content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
        isError: false,
      };
    }
  • Tool schema definition including name, description, and detailed inputSchema with properties and requirements for creating an issue.
    const CREATE_ISSUE_TOOL: Tool = {
      name: "create-issue",
      description: "Create a new issue in a project",
      inputSchema: {
        type: "object",
        properties: {
          project_id: {
            type: "string",
            description: "ID of the project where the issue should be created",
          },
          name: {
            type: "string",
            description: "Title of the issue",
          },
          description_html: {
            type: "string",
            description: "HTML description of the issue (required by Plane API)",
          },
          priority: {
            type: "string",
            description: "Priority of the issue (urgent, high, medium, low, none)",
            enum: ["urgent", "high", "medium", "low", "none"],
          },
          state_id: {
            type: "string",
            description: "ID of the state for this issue (optional)",
          },
          assignees: {
            type: "array",
            items: {
              type: "string",
            },
            description: "Array of user IDs to assign to this issue (optional)",
          },
        },
        required: ["project_id", "name"],
      },
    };
  • src/index.ts:263-271 (registration)
    Registration of the 'create-issue' tool (as CREATE_ISSUE_TOOL) in the listTools response handler, making it discoverable by MCP clients.
      tools: [
        LIST_PROJECTS_TOOL,
        GET_PROJECT_TOOL,
        CREATE_ISSUE_TOOL,
        LIST_ISSUES_TOOL,
        GET_ISSUE_TOOL,
        UPDATE_ISSUE_TOOL,
      ],
    }));
  • Shared helper function callPlaneAPI used by the create-issue handler to make authenticated HTTP requests to the Plane API.
    async function callPlaneAPI(
      endpoint: string,
      method: string,
      body?: any
    ): Promise<any> {
      const baseUrl = `${PLANE_HOST}/api/v1/workspaces/${PLANE_WORKSPACE_SLUG}`;
      const url = `${baseUrl}${endpoint}`;
    
      const options: RequestInit = {
        method,
        headers: {
          "Content-Type": "application/json",
          "X-API-Key": PLANE_API_KEY as string,
        },
      };
    
      if (body && (method === "POST" || method === "PATCH")) {
        options.body = JSON.stringify(body);
      }
    
      try {
        const response = await fetch(url, options);
    
        if (!response.ok) {
          let errorText;
          try {
            errorText = await response.text();
          } catch (parseError) {
            errorText = "Unable to parse error response";
          }
          throw new Error(
            `Plane API error: ${response.status} ${response.statusText}\n${errorText}`
          );
        }
    
        // For DELETE requests that return 204 No Content
        if (response.status === 204) {
          return { success: true };
        }
    
        return await response.json();
      } catch (error) {
        throw new Error(
          `Error calling Plane API: ${
            error instanceof Error ? error.message : String(error)
          }`
        );
      }
    }

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/kelvin6365/plane-mcp-server'

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