update_card
Modify card properties and move cards between columns in Focalboard using human-readable property names for task management updates.
Instructions
Update a card's properties, including moving it to different columns. Accepts human-readable property and column names.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cardId | Yes | The ID of the card to update | |
| boardId | Yes | The ID of the board the card belongs to | |
| title | No | New title for the card (optional) | |
| properties | No | Property values to update (e.g., {"Status": "In Progress", "Priority": "High"}). Use property names, not IDs. |
Implementation Reference
- src/index.ts:392-435 (handler)Main execution handler for the 'update_card' MCP tool. Parses arguments, conditionally updates card title, properties, or description using FocalboardClient methods, fetches the updated card, and returns it as JSON text content.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) } ] }; }
- src/index.ts:146-178 (schema)Tool registration definition including name, description, and input schema for parameter validation (cardId, boardId required; title, properties, description optional).{ 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'] } },
- src/index.ts:249-251 (registration)Registration of all tools list handler, which exposes the 'update_card' tool via the tools array.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; });
- src/focalboard-client.ts:318-352 (helper)Key helper function called by the handler to update card properties. Resolves human-readable property names and values to internal IDs and applies the patch.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); }
- src/focalboard-client.ts:256-265 (helper)Core helper function that performs the actual API PATCH request to update a card and refreshes the card data.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); }