update_tag
Modify existing tags in n8n workflows by updating their name and color properties through the n8n API.
Instructions
Update an existing tag
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| color | No | ||
| id | Yes | ||
| name | No |
Implementation Reference
- src/index.ts:525-529 (handler)MCP server handler method that processes the 'update_tag' tool call by invoking the N8nClient's updateTag method and formatting the 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/n8n-client.ts:638-703 (helper)N8nClient method implementing the tag update logic with fallback API endpoints (/rest/tags and /api/v1/tags), handling partial updates by fetching existing tag if necessary.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:205-205 (schema)JSON schema defining the input parameters for the 'update_tag' tool: id (required, string or number), optional name and color.{ 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/index.ts:306-307 (registration)Dispatch case in the CallToolRequestSchema handler that routes 'update_tag' calls to the handleUpdateTag method.case 'update_tag': return await this.handleUpdateTag(request.params.arguments as { id: string | number; name?: string; color?: string });