UNPKG

@grec0/mcp-s2s-asterisk

Version:

MCP server para asistente telefónico conversacional con Asterisk S2S

259 lines (258 loc) 8.65 kB
/** * @fileoverview Label operations for the MCP Kanban server * * This module provides functions for interacting with labels in the Planka Kanban board, * including creating, retrieving, updating, and deleting labels, as well as * adding and removing labels from cards. */ import { z } from "zod"; import { plankaRequest } from "../common/utils.js"; import { PlankaLabelSchema } from "../common/types.js"; /** * Valid color options for labels in Planka */ export const VALID_LABEL_COLORS = [ "berry-red", "pumpkin-orange", "lagoon-blue", "pink-tulip", "light-mud", "orange-peel", "bright-moss", "antique-blue", "dark-granite", "lagune-blue", "sunny-grass", "morning-sky", "light-orange", "midnight-blue", "tank-green", "gun-metal", "wet-moss", "red-burgundy", "light-concrete", "apricot-red", "desert-sand", "navy-blue", "egg-yellow", "coral-green", "light-cocoa", ]; /** * Schema for creating a new label * @property {string} boardId - The ID of the board to create the label in * @property {string} name - The name of the label * @property {string} color - The color of the label (must be one of the valid colors) * @property {number} [position] - The position of the label in the board (default: 65535) */ export const CreateLabelSchema = z.object({ boardId: z.string().describe("Board ID"), name: z.string().describe("Label name"), color: z.enum(VALID_LABEL_COLORS).describe("Label color"), position: z.number().optional().describe("Label position (default: 65535)"), }); /** * Schema for retrieving labels from a board * @property {string} boardId - The ID of the board to get labels from */ export const GetLabelsSchema = z.object({ boardId: z.string().describe("Board ID"), }); export const GetLabelSchema = z.object({ id: z.string().describe("Label ID"), }); /** * Schema for updating a label * @property {string} id - The ID of the label to update * @property {string} [name] - The new name for the label * @property {string} [color] - The new color for the label * @property {number} [position] - The new position for the label */ export const UpdateLabelSchema = z.object({ id: z.string().describe("Label ID"), name: z.string().optional().describe("Label name"), color: z.enum(VALID_LABEL_COLORS).optional().describe("Label color"), position: z.number().optional().describe("Label position"), }); /** * Schema for deleting a label * @property {string} id - The ID of the label to delete */ export const DeleteLabelSchema = z.object({ id: z.string().describe("Label ID"), }); /** * Schema for adding a label to a card * @property {string} cardId - The ID of the card to add the label to * @property {string} labelId - The ID of the label to add to the card */ export const AddLabelToCardSchema = z.object({ cardId: z.string().describe("Card ID"), labelId: z.string().describe("Label ID"), }); /** * Schema for removing a label from a card * @property {string} cardId - The ID of the card to remove the label from * @property {string} labelId - The ID of the label to remove from the card */ export const RemoveLabelFromCardSchema = z.object({ cardId: z.string().describe("Card ID"), labelId: z.string().describe("Label ID"), }); // Response schemas const LabelsResponseSchema = z.object({ items: z.array(PlankaLabelSchema), included: z.record(z.any()).optional(), }); const LabelResponseSchema = z.object({ item: PlankaLabelSchema, included: z.record(z.any()).optional(), }); const CardLabelResponseSchema = z.object({ item: z.object({ id: z.string(), cardId: z.string(), labelId: z.string(), createdAt: z.string(), updatedAt: z.string().nullable(), }), included: z.record(z.any()).optional(), }); // Function implementations /** * Creates a new label in a board * * @param {CreateLabelOptions} options - Options for creating the label * @param {string} options.boardId - The ID of the board to create the label in * @param {string} options.name - The name of the label * @param {string} options.color - The color of the label * @param {number} [options.position] - The position of the label in the board (default: 65535) * @returns {Promise<object>} The created label * @throws {Error} If the label creation fails */ export async function createLabel(options) { try { const response = await plankaRequest(`/api/boards/${options.boardId}/labels`, { method: "POST", body: { name: options.name, color: options.color, position: options.position, }, }); const parsedResponse = LabelResponseSchema.parse(response); return parsedResponse.item; } catch (error) { throw new Error(`Failed to create label: ${error instanceof Error ? error.message : String(error)}`); } } /** * Retrieves all labels for a specific board * * @param {string} boardId - The ID of the board to get labels from * @returns {Promise<Array<object>>} Array of labels in the board */ export async function getLabels(boardId) { try { // Get the board which includes labels in the response const response = await plankaRequest(`/api/boards/${boardId}`); // Check if the response has the expected structure if (response && typeof response === "object" && "included" in response && response.included && typeof response.included === "object" && "labels" in response.included) { // Get the labels from the included property const labels = response.included.labels; if (Array.isArray(labels)) { return labels; } } // If we can't find labels in the expected format, return an empty array return []; } catch (error) { // If all else fails, return an empty array return []; } } /** * Updates a label's properties * * @param {string} id - The ID of the label to update * @param {Partial<Omit<CreateLabelOptions, "boardId">>} options - The properties to update * @returns {Promise<object>} The updated label */ export async function updateLabel(id, options) { try { const response = await plankaRequest(`/api/labels/${id}`, { method: "PATCH", body: options, }); const parsedResponse = LabelResponseSchema.parse(response); return parsedResponse.item; } catch (error) { throw new Error(`Failed to update label: ${error instanceof Error ? error.message : String(error)}`); } } /** * Deletes a label by ID * * @param {string} id - The ID of the label to delete * @returns {Promise<{success: boolean}>} Success indicator */ export async function deleteLabel(id) { try { await plankaRequest(`/api/labels/${id}`, { method: "DELETE", }); return { success: true }; } catch (error) { throw new Error(`Failed to delete label: ${error instanceof Error ? error.message : String(error)}`); } } /** * Adds a label to a card * * @param {string} cardId - The ID of the card to add the label to * @param {string} labelId - The ID of the label to add to the card * @returns {Promise<object>} The created card-label relationship */ export async function addLabelToCard(cardId, labelId) { try { // The correct endpoint is /api/cards/{cardId}/labels with labelId in the body await plankaRequest(`/api/cards/${cardId}/labels`, { method: "POST", body: { labelId, }, }); return { success: true }; } catch (error) { throw new Error(`Failed to add label to card: ${error instanceof Error ? error.message : String(error)}`); } } /** * Removes a label from a card * * @param {string} cardId - The ID of the card to remove the label from * @param {string} labelId - The ID of the label to remove from the card * @returns {Promise<{success: boolean}>} Success indicator */ export async function removeLabelFromCard(cardId, labelId) { try { // The correct endpoint is /api/cards/{cardId}/labels/{labelId} await plankaRequest(`/api/cards/${cardId}/labels/${labelId}`, { method: "DELETE", }); return { success: true }; } catch (error) { throw new Error(`Failed to remove label from card: ${error instanceof Error ? error.message : String(error)}`); } }