update_tag
Modify existing workflow tags in n8n by changing their name or color to better organize and categorize automation processes.
Instructions
Update an existing tag
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| name | No | ||
| color | No |
Implementation Reference
- src/index.ts:525-529 (handler)The main MCP tool handler function for 'update_tag'. It extracts the id and update data from arguments, delegates the update to the N8nClient, and returns a formatted JSON success response.private async handleUpdateTag(args: { id: string | number; name?: string; color?: string }) { const { id, ...updateData } = args; const tag = await this.n8nClient.updateTag(id, updateData); return { content: [{ type: 'text', text: JSON.stringify(jsonSuccess(tag), null, 2) }] }; }
- src/index.ts:205-205 (registration)Registration of the 'update_tag' tool in the MCP server's tools list, including its name, description, and input schema definition.{ name: 'update_tag', description: 'Update an existing tag', inputSchema: { type: 'object', properties: { id: { oneOf: [{ type: 'string' }, { type: 'number' }] }, name: { type: 'string' }, color: { type: 'string' } }, required: ['id'] } },
- src/n8n-client.ts:638-703 (helper)The N8nClient helper method that implements the actual tag update logic via fallback HTTP strategies: PATCH /rest/tags/{id} then PUT /api/v1/tags/{id}, with merging for partial updates and detailed error handling.async updateTag(id: string | number, tag: Partial<Omit<N8nTag, 'id' | 'createdAt' | 'updatedAt'>>): Promise<N8nTag> { const attempts: EndpointAttempt[] = []; // Strategy 1: Try PATCH on /rest/tags/{id} const patchRest = await this.requestRest('PATCH', `/rest/tags/${id}`, tag); attempts.push({ endpoint: `/rest/tags/${id}`, method: 'PATCH', status: patchRest.status, message: String(patchRest.error?.message ?? patchRest.error ?? '') }); if (patchRest.ok && patchRest.data) { // Unwrap response if needed const result = (patchRest.data as any)?.data || patchRest.data; return result as N8nTag; } // Strategy 2: Try PUT on /api/v1/tags/{id} // PUT typically requires a full payload, so if the incoming tag is partial, fetch and merge try { let fullPayload = tag; // Check if we need to fetch the existing tag for a merge // If name is missing, we need to fetch the existing tag if (!tag.name) { try { const existingTag = await this.getTag(id); // Merge existing tag with provided updates fullPayload = { name: existingTag.name, ...tag }; } catch (fetchError) { // If we can't fetch, try the PUT anyway with what we have logger.debug('Could not fetch existing tag for merge', { id, error: fetchError }); } } const response = await this.api.put<N8nApiResponse<N8nTag>>(`/tags/${id}`, fullPayload); attempts.push({ endpoint: `/api/v1/tags/${id}`, method: 'PUT', status: response.status, message: undefined }); return response.data.data; } catch (error: any) { attempts.push({ endpoint: `/api/v1/tags/${id}`, method: 'PUT', status: error.response?.status || 0, message: String(error.response?.data?.message ?? error.message ?? error ?? '') }); // If updating color specifically and all endpoints failed, provide helpful message if (tag.color && !tag.name) { const errorMsg = `Unable to update tag color. Attempted endpoints: ${attempts.map(a => `${a.method} ${a.endpoint} (${a.status})`).join(', ')}. Tag color may need to be set via the n8n UI for this instance.`; const err = new Error(errorMsg); (err as any).attempts = attempts; throw err; } throw error; } }
- src/index.ts:306-307 (handler)Dispatch case in the main CallToolRequestHandler that routes 'update_tag' calls to the specific handleUpdateTag method.case 'update_tag': return await this.handleUpdateTag(request.params.arguments as { id: string | number; name?: string; color?: string });