Skip to main content
Glama

update_card

Modify card properties, update descriptions, or move cards between columns in Focalboard using human-readable property names.

Instructions

Update a card's properties, including moving it to different columns. Accepts human-readable property and column names.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cardIdYesThe ID of the card to update
boardIdYesThe ID of the board the card belongs to
titleNoNew title for the card (optional)
propertiesNoProperty values to update (e.g., {"Status": "In Progress", "Priority": "High"}). Use property names, not IDs.
descriptionNoUpdate or set the description/content for the card in markdown format (optional)

Implementation Reference

  • MCP tool handler for 'update_card'. Validates inputs (requires cardId and boardId), conditionally updates title via updateCard, properties via updateCardProperties, description via setCardDescription, then fetches and returns the updated card JSON.
    case 'update_card': { const cardId = args?.cardId as string; const boardId = args?.boardId as string; const title = args?.title as string; const properties = (args?.properties as Record<string, string>) || {}; const description = args?.description as string | undefined; if (!cardId || !boardId) { throw new Error('cardId and boardId are required'); } if (!title && Object.keys(properties).length === 0 && !description) { throw new Error('Either title, properties, or description must be provided'); } let card; // Update title if provided if (title) { card = await focalboard.updateCard(boardId, cardId, { title }); } // Update properties if provided if (Object.keys(properties).length > 0) { card = await focalboard.updateCardProperties(cardId, boardId, properties); } // Update description if provided if (description) { await focalboard.setCardDescription(boardId, cardId, description); } // Fetch the updated card card = await focalboard.getCard(cardId); return { content: [ { type: 'text', text: JSON.stringify(card, null, 2) } ] }; }
  • Tool definition including name, description, and input schema for 'update_card'. Specifies required parameters (cardId, boardId) and optional (title, properties as object of strings, description).
    { name: 'update_card', description: 'Update a card\'s properties, including moving it to different columns. Accepts human-readable property and column names.', inputSchema: { type: 'object', properties: { cardId: { type: 'string', description: 'The ID of the card to update' }, boardId: { type: 'string', description: 'The ID of the board the card belongs to' }, title: { type: 'string', description: 'New title for the card (optional)' }, properties: { type: 'object', description: 'Property values to update (e.g., {"Status": "In Progress", "Priority": "High"}). Use property names, not IDs.', additionalProperties: { type: 'string' } }, description: { type: 'string', description: 'Update or set the description/content for the card in markdown format (optional)' } }, required: ['cardId', 'boardId'] } },
  • Helper function updateCardProperties that resolves human-readable property names and values to internal IDs by fetching the board, then applies the patch via updateCard. Used in the tool handler for properties updates.
    async updateCardProperties( cardId: string, boardId: string, properties: Record<string, string> ): Promise<Card> { const board = await this.getBoard(boardId); const propertyUpdates: Record<string, string> = {}; for (const [propName, value] of Object.entries(properties)) { const property = this.findPropertyByName(board, propName); if (!property) { throw new Error(`Property '${propName}' not found on board`); } // For select/multiSelect types, resolve option ID if (property.type === 'select' || property.type === 'multiSelect') { const optionId = this.findPropertyOption(property, value); if (!optionId) { throw new Error(`Option '${value}' not found in property '${propName}'`); } propertyUpdates[property.id] = optionId; } else { // For other types, use the value directly propertyUpdates[property.id] = value; } } const patch: CardPatch = { updatedFields: { properties: propertyUpdates } }; return this.updateCard(boardId, cardId, patch); }
  • Core helper method to PATCH update a card via the Focalboard API endpoint, then refetches the card since the API returns no body. Used for title updates and by updateCardProperties.
    async updateCard(boardId: string, cardId: string, patch: CardPatch): Promise<Card> { await this.makeRequest<void>( `/boards/${boardId}/blocks/${cardId}`, 'PATCH', patch ); // Fetch and return the updated card since PATCH returns empty return this.getCard(cardId); }
  • Helper to set or update card description by managing text blocks: updates existing or creates new via createTextBlock. Used in tool handler for description updates.
    async setCardDescription(boardId: string, cardId: string, description: string): Promise<Block> { // Get existing content blocks const contentBlocks = await this.getCardContent(cardId); const textBlocks = contentBlocks.filter(block => block.type === 'text'); if (textBlocks.length > 0) { // Update the first text block directly const textBlock = textBlocks[0]; await this.makeRequest<void>( `/boards/${boardId}/blocks/${textBlock.id}`, 'PATCH', { title: description } ); // Fetch and return the updated block const updatedBlocks = await this.makeRequest<Block[]>( `/boards/${boardId}/blocks`, 'GET', undefined, { block_id: textBlock.id } ); return updatedBlocks[0]; } else { // Create a new text block return this.createTextBlock(boardId, cardId, description); } }

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/gmjuhasz/focalboard-mcp-server'

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