diff --git a/packages/cli/src/modules/mcp/__tests__/create-workflow-from-code.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/create-workflow-from-code.tool.test.ts index 868bc9f4d56..83cac267e53 100644 --- a/packages/cli/src/modules/mcp/__tests__/create-workflow-from-code.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/create-workflow-from-code.tool.test.ts @@ -954,7 +954,7 @@ describe('create-workflow-from-code MCP tool', () => { }, { nodeName: 'OpenAI', - credentialName: 'n8n credits', + credentialName: 'Gateway credits', credentialType: 'openAiApi', source: 'aiGateway', }, diff --git a/packages/cli/src/modules/mcp/__tests__/credentials-auto-assign.test.ts b/packages/cli/src/modules/mcp/__tests__/credentials-auto-assign.test.ts index cc549ea21cd..595fc2b2b38 100644 --- a/packages/cli/src/modules/mcp/__tests__/credentials-auto-assign.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/credentials-auto-assign.test.ts @@ -397,12 +397,12 @@ describe('autoPopulateNodeCredentials', () => { ); expect(node.credentials).toEqual({ - slackApi: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + slackApi: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }); expect(result.assignments).toEqual([ { nodeName: 'Test Node', - credentialName: 'n8n credits', + credentialName: 'Gateway credits', credentialType: 'slackApi', source: 'aiGateway', }, @@ -473,13 +473,13 @@ describe('autoPopulateNodeCredentials', () => { ); expect(node.credentials).toEqual({ - serviceApiKey: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + serviceApiKey: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }); expect(node.parameters.authentication).toBe('apiKey'); expect(result.assignments).toEqual([ { nodeName: 'Test Node', - credentialName: 'n8n credits', + credentialName: 'Gateway credits', credentialType: 'serviceApiKey', source: 'aiGateway', }, @@ -551,7 +551,7 @@ describe('autoPopulateNodeCredentials', () => { ); expect(node.credentials).toEqual({ - serviceApiKey: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + serviceApiKey: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }); expect(node.parameters.authentication).toBe('apiKey'); }); @@ -616,7 +616,7 @@ describe('autoPopulateNodeCredentials', () => { ); expect(node.credentials).toEqual({ - serviceApiKey: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + serviceApiKey: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }); expect(node.parameters.authentication).toBe('apiKeyLegacy'); }); @@ -807,7 +807,7 @@ describe('autoPopulateNodeCredentials', () => { // Canonicalized to the sentinel and kept — the explicit n8n Connect request // wins over the owned credential, and no assignment is recorded for it. expect(node.credentials).toEqual({ - slackApi: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + slackApi: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }); expect(result.assignments).toEqual([]); expect(result.outcomes).toEqual([]); diff --git a/packages/cli/src/modules/mcp/__tests__/get-workflow-details.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/get-workflow-details.tool.test.ts index 54183b8df7b..7e4744b0c83 100644 --- a/packages/cli/src/modules/mcp/__tests__/get-workflow-details.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/get-workflow-details.tool.test.ts @@ -124,7 +124,7 @@ describe('get-workflow-details MCP tool', () => { disabled: false, parameters: {}, credentials: { - openAiApi: { id: null, name: 'n8n credits', __aiGatewayManaged: true }, + openAiApi: { id: null, name: 'Gateway credits', __aiGatewayManaged: true }, }, }, { diff --git a/packages/cli/src/modules/mcp/__tests__/get-workflow-node-types.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/get-workflow-node-types.tool.test.ts index 839909944af..75087cd0714 100644 --- a/packages/cli/src/modules/mcp/__tests__/get-workflow-node-types.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/get-workflow-node-types.tool.test.ts @@ -50,7 +50,7 @@ describe('get-workflow-node-types MCP tool', () => { expect(result.structuredContent).toEqual({ definitions: 'typescript definitions' }); }); - test('adds n8nConnect block when gateway is available', async () => { + test('adds gatewayCredits block when gateway is available', async () => { aiGatewayService.isAvailable.mockResolvedValue({ available: true, config: { @@ -68,18 +68,18 @@ describe('get-workflow-node-types MCP tool', () => { expect(result.structuredContent).toEqual({ definitions: 'typescript definitions', - n8nConnect: { + gatewayCredits: { credentialTypes: ['openAiApi'], nodes: ['@n8n/n8n-nodes-langchain.openAi'], }, }); // Also mirrored into the unstructured content for text-only clients. expect((result.content[0] as { text: string }).text).toBe( - 'typescript definitions\n\nn8nConnect: {"credentialTypes":["openAiApi"],"nodes":["@n8n/n8n-nodes-langchain.openAi"]}', + 'typescript definitions\n\ngatewayCredits: {"credentialTypes":["openAiApi"],"nodes":["@n8n/n8n-nodes-langchain.openAi"]}', ); }); - test('omits n8nConnect block when unavailable', async () => { + test('omits gatewayCredits block when unavailable', async () => { const tool = createTool(); const result = await tool.handler( { nodeIds: [{ nodeId: 'n8n-nodes-base.slack' }] }, diff --git a/packages/cli/src/modules/mcp/__tests__/list-credentials.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/list-credentials.tool.test.ts index a48c6765b87..12a0f842da8 100644 --- a/packages/cli/src/modules/mcp/__tests__/list-credentials.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/list-credentials.tool.test.ts @@ -275,7 +275,7 @@ describe('list-credentials MCP tool', () => { ); }); - describe('n8nConnect block', () => { + describe('gatewayCredits block', () => { async function callHandler(opts: { available?: boolean } = {}) { const { credentialsService, telemetry } = createMocks([buildCredential()]); const { aiGatewayService } = makeAiGatewayMocks(opts); @@ -298,21 +298,21 @@ describe('list-credentials MCP tool', () => { return result.structuredContent as { data: unknown[]; count: number; - n8nConnect?: { credentialTypes: string[]; nodes: string[] }; + gatewayCredits?: { credentialTypes: string[]; nodes: string[] }; }; } - test('includes n8nConnect block when gateway is available', async () => { + test('includes gatewayCredits block when gateway is available', async () => { const structured = await callHandler({ available: true }); - expect(structured.n8nConnect).toEqual({ + expect(structured.gatewayCredits).toEqual({ credentialTypes: ['openAiApi'], nodes: ['@n8n/n8n-nodes-langchain.openAi'], }); }); - test('omits n8nConnect block when unavailable', async () => { + test('omits gatewayCredits block when unavailable', async () => { const structured = await callHandler({ available: false }); - expect(structured.n8nConnect).toBeUndefined(); + expect(structured.gatewayCredits).toBeUndefined(); }); }); }); diff --git a/packages/cli/src/modules/mcp/__tests__/list-n8n-connect-services.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/list-n8n-gateway-services.tool.test.ts similarity index 84% rename from packages/cli/src/modules/mcp/__tests__/list-n8n-connect-services.tool.test.ts rename to packages/cli/src/modules/mcp/__tests__/list-n8n-gateway-services.tool.test.ts index 62d5829ea02..5ebb9b47f41 100644 --- a/packages/cli/src/modules/mcp/__tests__/list-n8n-connect-services.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/list-n8n-gateway-services.tool.test.ts @@ -6,7 +6,7 @@ import { mock } from 'vitest-mock-extended'; import type { AiGatewayService } from '@/services/ai-gateway.service'; import { Telemetry } from '@/telemetry'; -import { createListN8nConnectServicesTool } from '../tools/list-n8n-connect-services.tool'; +import { createListN8nGatewayServicesTool } from '../tools/list-n8n-gateway-services.tool'; const user = Object.assign(new User(), { id: 'user-1' }); @@ -39,11 +39,11 @@ function makeMocks(opts: { available?: boolean; config?: AiGatewayConfigDto } = return { aiGatewayService, telemetry }; } -describe('list_n8n_connect_services MCP tool', () => { - test('registers under the name list_n8n_connect_services', () => { +describe('list_n8n_gateway_services MCP tool', () => { + test('registers under the name list_n8n_gateway_services', () => { const { aiGatewayService, telemetry } = makeMocks(); - const tool = createListN8nConnectServicesTool(user, aiGatewayService, telemetry); - expect(tool.name).toBe('list_n8n_connect_services'); + const tool = createListN8nGatewayServicesTool(user, aiGatewayService, telemetry); + expect(tool.name).toBe('list_n8n_gateway_services'); expect(tool.config.annotations).toMatchObject({ readOnlyHint: true, destructiveHint: false, @@ -54,7 +54,7 @@ describe('list_n8n_connect_services MCP tool', () => { test('returns full coverage payload when available', async () => { const { aiGatewayService, telemetry } = makeMocks({ available: true }); - const tool = createListN8nConnectServicesTool(user, aiGatewayService, telemetry); + const tool = createListN8nGatewayServicesTool(user, aiGatewayService, telemetry); const result = await tool.handler({}, {} as never); expect(result.structuredContent).toEqual({ available: true, @@ -70,20 +70,20 @@ describe('list_n8n_connect_services MCP tool', () => { test('returns { available: false } when unavailable', async () => { const { aiGatewayService, telemetry } = makeMocks({ available: false }); - const tool = createListN8nConnectServicesTool(user, aiGatewayService, telemetry); + const tool = createListN8nGatewayServicesTool(user, aiGatewayService, telemetry); const result = await tool.handler({}, {} as never); expect(result.structuredContent).toEqual({ available: false }); }); test('emits USER_CALLED_MCP_TOOL_EVENT with tool_name and success', async () => { const { aiGatewayService, telemetry } = makeMocks(); - const tool = createListN8nConnectServicesTool(user, aiGatewayService, telemetry); + const tool = createListN8nGatewayServicesTool(user, aiGatewayService, telemetry); await tool.handler({}, {} as never); expect(telemetry.track).toHaveBeenCalledWith( 'User called mcp tool', expect.objectContaining({ user_id: 'user-1', - tool_name: 'list_n8n_connect_services', + tool_name: 'list_n8n_gateway_services', results: { success: true, data: { available: true } }, }), ); diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-instructions.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-instructions.test.ts index 598284328b1..5e490cfe8ef 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-instructions.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-instructions.test.ts @@ -4,7 +4,7 @@ describe('getMcpInstructions', () => { test('returns intro-only string when builder is disabled', () => { const instructions = getMcpInstructions({ isBuilderEnabled: false }); expect(instructions).toContain('official MCP server for n8n'); - expect(instructions).not.toContain('n8nConnect'); + expect(instructions).not.toContain('gatewayCredits'); }); test('includes n8n credits hint when builder is enabled and n8n Connect is available', () => { @@ -12,10 +12,10 @@ describe('getMcpInstructions', () => { isBuilderEnabled: true, isN8nConnectAvailable: true, }); - expect(instructions).toContain('nodes covered by n8n credits'); - expect(instructions).toContain('n8nConnect.nodes'); - expect(instructions).toContain('n8n credits'); - expect(instructions).toContain('list_n8n_connect_services'); + expect(instructions).toContain('nodes covered by Gateway credits'); + expect(instructions).toContain('gatewayCredits.nodes'); + expect(instructions).toContain('Gateway credits'); + expect(instructions).toContain('list_n8n_gateway_services'); }); test('omits n8n credits hint when n8n Connect is not available', () => { @@ -24,14 +24,14 @@ describe('getMcpInstructions', () => { isN8nConnectAvailable: false, }); expect(instructions).toContain('official MCP server for n8n'); - expect(instructions).not.toContain('n8n credits'); - expect(instructions).not.toContain('n8nConnect'); - expect(instructions).not.toContain('list_n8n_connect_services'); + expect(instructions).not.toContain('Gateway credits'); + expect(instructions).not.toContain('gatewayCredits'); + expect(instructions).not.toContain('list_n8n_gateway_services'); }); test('omits n8n credits hint by default', () => { const instructions = getMcpInstructions({ isBuilderEnabled: true }); - expect(instructions).not.toContain('n8n credits'); + expect(instructions).not.toContain('Gateway credits'); }); describe('node groups pointer', () => { diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-scopes.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-scopes.test.ts index 482b3b16c95..57c3daac5f9 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-scopes.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-scopes.test.ts @@ -82,6 +82,10 @@ describe('getAllowedToolNames', () => { it('grants only call_agent with agent:execute', () => { expect(getAllowedToolNames(['agent:execute'])).toEqual(new Set(['call_agent'])); }); + + it('exposes the renamed list_n8n_gateway_services tool via credential:read', () => { + expect(getAllowedToolNames(['credential:read'])).toContain('list_n8n_gateway_services'); + }); }); describe('McpService scope enforcement', () => { diff --git a/packages/cli/src/modules/mcp/__tests__/search-workflow-nodes.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/search-workflow-nodes.tool.test.ts index bc0a10bde5a..886bb2c5435 100644 --- a/packages/cli/src/modules/mcp/__tests__/search-workflow-nodes.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/search-workflow-nodes.tool.test.ts @@ -118,8 +118,8 @@ describe('search-workflow-nodes MCP tool', () => { ); }); - describe('n8nConnect block', () => { - test('includes n8nConnect block when gateway is available', async () => { + describe('gatewayCredits block', () => { + test('includes gatewayCredits block when gateway is available', async () => { aiGatewayService.isAvailable.mockResolvedValue({ available: true, config: { @@ -134,18 +134,18 @@ describe('search-workflow-nodes MCP tool', () => { expect(result.structuredContent).toEqual({ results: 'search-result', - n8nConnect: { + gatewayCredits: { credentialTypes: ['openAiApi'], nodes: ['@n8n/n8n-nodes-langchain.openAi'], }, }); // Also mirrored into the unstructured content for text-only clients. expect((result.content[0] as { text: string }).text).toBe( - 'search-result\n\nn8nConnect: {"credentialTypes":["openAiApi"],"nodes":["@n8n/n8n-nodes-langchain.openAi"]}', + 'search-result\n\ngatewayCredits: {"credentialTypes":["openAiApi"],"nodes":["@n8n/n8n-nodes-langchain.openAi"]}', ); }); - test('omits n8nConnect block when unavailable', async () => { + test('omits gatewayCredits block when unavailable', async () => { const tool = createTool(); const result = await tool.handler({ queries: ['openai'] }, {} as never); expect(result.structuredContent).toEqual({ results: 'search-result' }); diff --git a/packages/cli/src/modules/mcp/__tests__/update-workflow.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/update-workflow.tool.test.ts index 170cd7b5b34..a3b2f99b10b 100644 --- a/packages/cli/src/modules/mcp/__tests__/update-workflow.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/update-workflow.tool.test.ts @@ -1958,7 +1958,7 @@ describe('update-workflow MCP tool', () => { }, { nodeName: 'D', - credentialName: 'n8n credits', + credentialName: 'Gateway credits', credentialType: 'openAiApi', source: 'aiGateway', }, @@ -1983,7 +1983,7 @@ describe('update-workflow MCP tool', () => { { nodeName: 'C', credentialName: 'My Slack', credentialType: 'slackApi', source: 'user' }, { nodeName: 'D', - credentialName: 'n8n credits', + credentialName: 'Gateway credits', credentialType: 'openAiApi', source: 'aiGateway', }, diff --git a/packages/cli/src/modules/mcp/mcp-scopes.ts b/packages/cli/src/modules/mcp/mcp-scopes.ts index 838bc33150d..1d460841527 100644 --- a/packages/cli/src/modules/mcp/mcp-scopes.ts +++ b/packages/cli/src/modules/mcp/mcp-scopes.ts @@ -73,7 +73,7 @@ export const TOOLS_BY_SCOPE: Record = { 'agent:execute': ['call_agent'], // explore_node_resources queries external services with stored credentials, // so it must sit behind the credential scope rather than a workflow one. - 'credential:read': ['list_credentials', 'list_n8n_connect_services', 'explore_node_resources'], + 'credential:read': ['list_credentials', 'list_n8n_gateway_services', 'explore_node_resources'], 'dataTable:read': ['search_data_tables', 'get_data_table_rows'], // Writing requires finding tables, so search rides along. 'dataTable:write': [ diff --git a/packages/cli/src/modules/mcp/mcp.constants.ts b/packages/cli/src/modules/mcp/mcp.constants.ts index 1cda4f998cb..fa277fc0252 100644 --- a/packages/cli/src/modules/mcp/mcp.constants.ts +++ b/packages/cli/src/modules/mcp/mcp.constants.ts @@ -50,7 +50,7 @@ export const MISSING_PROTOCOL_VERSION_ERROR_MESSAGE = /** * Tool name constants */ -export const LIST_N8N_CONNECT_SERVICES_TOOL_NAME = 'list_n8n_connect_services'; +export const LIST_N8N_GATEWAY_SERVICES_TOOL_NAME = 'list_n8n_gateway_services'; export const MCP_CALL_AGENT_TOOL_NAME = 'call_agent'; export const MCP_CREATE_AGENT_TOOL_NAME = 'create_agent'; diff --git a/packages/cli/src/modules/mcp/mcp.service.ts b/packages/cli/src/modules/mcp/mcp.service.ts index 1b4b50b71de..c8fdcfe7021 100644 --- a/packages/cli/src/modules/mcp/mcp.service.ts +++ b/packages/cli/src/modules/mcp/mcp.service.ts @@ -77,7 +77,7 @@ import { createGetWorkflowHistoryTool } from './tools/get-workflow-history.tool' import { createGetWorkflowVersionTool } from './tools/get-workflow-version.tool'; import { createGetWorkflowVersionsDiffTool } from './tools/get-workflow-versions-diff.tool'; import { createListCredentialsTool } from './tools/list-credentials.tool'; -import { createListN8nConnectServicesTool } from './tools/list-n8n-connect-services.tool'; +import { createListN8nGatewayServicesTool } from './tools/list-n8n-gateway-services.tool'; import { createListTagsTool } from './tools/list-tags.tool'; import { createMoveWorkflowsToFolderTool } from './tools/move-workflows-to-folder.tool'; import { createPrepareTestPinDataTool } from './tools/prepare-workflow-pin-data.tool'; @@ -560,13 +560,13 @@ export class McpService { this.aiGatewayService, ); - const listN8nConnectServicesTool = createListN8nConnectServicesTool( + const listN8nGatewayServicesTool = createListN8nGatewayServicesTool( user, this.aiGatewayService, this.telemetry, ); registerIfAllowed(listCredentialsTool); - registerIfAllowed(listN8nConnectServicesTool); + registerIfAllowed(listN8nGatewayServicesTool); if (!this.globalConfig.tags.disabled) { const listTagsTool = createListTagsTool(user, this.tagService, this.telemetry); diff --git a/packages/cli/src/modules/mcp/tools/list-credentials.tool.ts b/packages/cli/src/modules/mcp/tools/list-credentials.tool.ts index 99ec077b3aa..635544955d4 100644 --- a/packages/cli/src/modules/mcp/tools/list-credentials.tool.ts +++ b/packages/cli/src/modules/mcp/tools/list-credentials.tool.ts @@ -7,7 +7,7 @@ import type { AiGatewayService } from '@/services/ai-gateway.service'; import type { Telemetry } from '@/telemetry'; import { toN8nConnectCoverage } from '../mcp-ai-gateway.helper'; -import { LIST_N8N_CONNECT_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT } from '../mcp.constants'; +import { LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT } from '../mcp.constants'; import type { N8nConnectCoverage, ToolDefinition, @@ -51,14 +51,14 @@ const n8nConnectSchema = z .object({ credentialTypes: z .array(z.string()) - .describe('Credential type names that n8n credits can provide (e.g. "openAiApi").'), + .describe('Credential type names that Gateway credits can provide (e.g. "openAiApi").'), nodes: z .array(z.string()) - .describe('Node types covered by n8n credits (e.g. "@n8n/n8n-nodes-langchain.openAi").'), + .describe('Node types covered by Gateway credits (e.g. "@n8n/n8n-nodes-langchain.openAi").'), }) .optional() .describe( - `Present when n8n credits is available for this instance. Omitted otherwise. Candidate coverage only — actual eligibility for a managed credential also depends on the node action, minimum type version, and hidden properties; call ${LIST_N8N_CONNECT_SERVICES_TOOL_NAME} for the authoritative contract.`, + `Present when Gateway credits are available for this instance. Omitted otherwise. Candidate coverage only — actual eligibility for a managed credential also depends on the node action, minimum type version, and hidden properties; call ${LIST_N8N_GATEWAY_SERVICES_TOOL_NAME} for the authoritative contract.`, ); const outputSchema = { @@ -80,7 +80,7 @@ const outputSchema = { ) .describe('List of credentials accessible to the current user'), count: z.number().int().min(0).describe('Number of credentials returned'), - n8nConnect: n8nConnectSchema, + gatewayCredits: n8nConnectSchema, error: z.string().optional().describe('Error message when the tool failed'), } satisfies z.ZodRawShape; @@ -105,7 +105,7 @@ export type ListCredentialsItem = { export type ListCredentialsResult = { data: ListCredentialsItem[]; count: number; - n8nConnect?: N8nConnectCoverage; + gatewayCredits?: N8nConnectCoverage; error?: string; }; @@ -152,7 +152,7 @@ export const createListCredentialsTool = ( }); const coverage = toN8nConnectCoverage(await aiGatewayService.isAvailable()); - if (coverage) payload.n8nConnect = coverage; + if (coverage) payload.gatewayCredits = coverage; telemetryPayload.results = { success: true, diff --git a/packages/cli/src/modules/mcp/tools/list-n8n-connect-services.tool.ts b/packages/cli/src/modules/mcp/tools/list-n8n-gateway-services.tool.ts similarity index 67% rename from packages/cli/src/modules/mcp/tools/list-n8n-connect-services.tool.ts rename to packages/cli/src/modules/mcp/tools/list-n8n-gateway-services.tool.ts index c2c1174c171..7d7edc98c7c 100644 --- a/packages/cli/src/modules/mcp/tools/list-n8n-connect-services.tool.ts +++ b/packages/cli/src/modules/mcp/tools/list-n8n-gateway-services.tool.ts @@ -4,7 +4,7 @@ import z from 'zod'; import type { AiGatewayService } from '@/services/ai-gateway.service'; import type { Telemetry } from '@/telemetry'; -import { LIST_N8N_CONNECT_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT } from '../mcp.constants'; +import { LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT } from '../mcp.constants'; import type { ToolDefinition, UserCalledMCPToolEventPayload } from '../mcp.types'; const inputSchema = {} satisfies z.ZodRawShape; @@ -13,16 +13,16 @@ const outputSchema = { available: z .boolean() .describe( - 'True when n8n credits is available for this instance. When false, the remaining fields are omitted.', + 'True when Gateway credits are available for this instance. When false, the remaining fields are omitted.', ), credentialTypes: z .array(z.string()) .optional() - .describe('Credential type names Connect can provide (e.g. "openAiApi").'), + .describe('Credential type names Gateway credits can provide (e.g. "openAiApi").'), nodes: z .array(z.string()) .optional() - .describe('Node types Connect covers (e.g. "@n8n/n8n-nodes-langchain.openAi").'), + .describe('Node types Gateway credits cover (e.g. "@n8n/n8n-nodes-langchain.openAi").'), supportedActions: z .record(z.record(z.array(z.string()))) .optional() @@ -32,35 +32,37 @@ const outputSchema = { minNodeTypeVersion: z .record(z.number()) .optional() - .describe('Minimum `typeVersion` per node type for Connect coverage.'), + .describe('Minimum `typeVersion` per node type for Gateway credits coverage.'), hiddenNodeProperties: z .record(z.array(z.string())) .optional() - .describe('Per-node property names hidden from the user when Connect provides the credential.'), + .describe( + 'Per-node property names hidden from the user when Gateway credits provide the credential.', + ), } satisfies z.ZodRawShape; /** - * Returns the current n8n Connect coverage snapshot for the - * instance: which node types and credential types Connect can serve, plus + * Returns the current Gateway credits coverage snapshot for the + * instance: which node types and credential types Gateway credits can serve, plus * per-node action allowlists, min versions, and hidden properties. * - * Read-only. Omits all coverage fields when Connect is unavailable + * Read-only. Omits all coverage fields when Gateway credits are unavailable * (unlicensed, misconfigured, or gateway down) — callers should key on * `available: false` and fall back to user credentials. */ -export const createListN8nConnectServicesTool = ( +export const createListN8nGatewayServicesTool = ( user: User, aiGatewayService: AiGatewayService, telemetry: Telemetry, ): ToolDefinition => ({ - name: LIST_N8N_CONNECT_SERVICES_TOOL_NAME, + name: LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, config: { description: - 'List n8n credits coverage: node and credential types the platform can provide managed credentials for, plus supported resource+operation combinations, minimum type versions, and hidden node properties. Use this to decide which nodes let the user skip credential setup.', + 'List Gateway credits coverage: node and credential types the platform can provide managed credentials for, plus supported resource+operation combinations, minimum type versions, and hidden node properties. Use this to decide which nodes let the user skip credential setup.', inputSchema, outputSchema, annotations: { - title: 'List services available with n8n credits', + title: 'List services available with Gateway credits', readOnlyHint: true, destructiveHint: false, idempotentHint: true, @@ -70,7 +72,7 @@ export const createListN8nConnectServicesTool = ( handler: async () => { const telemetryPayload: UserCalledMCPToolEventPayload = { user_id: user.id, - tool_name: LIST_N8N_CONNECT_SERVICES_TOOL_NAME, + tool_name: LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, }; const availability = await aiGatewayService.isAvailable(); diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts index 4cb55eb3422..7b3cd23e5b0 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/create-workflow-from-code.tool.ts @@ -128,7 +128,7 @@ const outputSchema = { .enum(['user', 'aiGateway']) .optional() .describe( - 'Where the credential came from: "user" for an existing user credential, "aiGateway" for a credential managed via n8n credits.', + 'Where the credential came from: "user" for an existing user credential, "aiGateway" for a credential managed via Gateway credits.', ), }), ) diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/credentials-auto-assign.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/credentials-auto-assign.ts index 4d395393ebd..1962e9aac63 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/credentials-auto-assign.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/credentials-auto-assign.ts @@ -20,7 +20,7 @@ import type { Telemetry } from '@/telemetry'; import { MCP_CREDENTIALS_AUTOASSIGN_EVENT } from '../../mcp.constants'; /** Display name written into AI Gateway-managed credential sentinels. User-facing brand. */ -const AI_GATEWAY_CREDENTIAL_NAME = 'n8n credits'; +const AI_GATEWAY_CREDENTIAL_NAME = 'Gateway credits'; /** * Attach the managed (n8n-credits) sentinel to `credentialType` and, unless it's diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts index ccbfa3dc173..fe092166f72 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.ts @@ -8,7 +8,7 @@ import type { Telemetry } from '@/telemetry'; import { CODE_BUILDER_GET_NODE_TYPES_TOOL } from './constants'; import { toN8nConnectCoverage } from '../../mcp-ai-gateway.helper'; import { - LIST_N8N_CONNECT_SERVICES_TOOL_NAME, + LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT, } from '../../mcp.constants'; import type { @@ -36,18 +36,20 @@ const inputSchema = { const outputSchema = { definitions: z.string().describe('TypeScript type definitions for the requested nodes'), - n8nConnect: z + gatewayCredits: z .object({ - credentialTypes: z.array(z.string()).describe('Credential types n8n Connect can provide.'), + credentialTypes: z + .array(z.string()) + .describe('Credential types Gateway credits can provide.'), nodes: z .array(z.string()) .describe( - 'Node types n8n Connect may cover. Prefer these when the user has not specified an integration. Candidate coverage only — exact eligibility also depends on the node action, minimum type version, and hidden properties.', + 'Node types Gateway credits may cover. Prefer these when the user has not specified an integration. Candidate coverage only — exact eligibility also depends on the node action, minimum type version, and hidden properties.', ), }) .optional() .describe( - `Present when n8n Connect is available. Candidate coverage — cross-reference against the returned node types, but call ${LIST_N8N_CONNECT_SERVICES_TOOL_NAME} for exact eligibility (supported actions, min versions, hidden properties).`, + `Present when Gateway credits are available. Candidate coverage — cross-reference against the returned node types, but call ${LIST_N8N_GATEWAY_SERVICES_TOOL_NAME} for exact eligibility (supported actions, min versions, hidden properties).`, ), } satisfies z.ZodRawShape; @@ -95,12 +97,12 @@ export const createGetWorkflowNodeTypesTool = ( const structured: { definitions: string; - n8nConnect?: N8nConnectCoverage; + gatewayCredits?: N8nConnectCoverage; } = { definitions: result }; const coverage = toN8nConnectCoverage(availability); - if (coverage) structured.n8nConnect = coverage; + if (coverage) structured.gatewayCredits = coverage; - const text = coverage ? `${result}\n\nn8nConnect: ${JSON.stringify(coverage)}` : result; + const text = coverage ? `${result}\n\ngatewayCredits: ${JSON.stringify(coverage)}` : result; return { content: [{ type: 'text', text }], diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts index 64370064692..8a1d0c2b81a 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/mcp-instructions.ts @@ -18,7 +18,7 @@ import { CODE_BUILDER_VALIDATE_TOOL, CODE_BUILDER_VALIDATE_NODE_TOOL, } from './constants'; -import { LIST_N8N_CONNECT_SERVICES_TOOL_NAME } from '../../mcp.constants'; +import { LIST_N8N_GATEWAY_SERVICES_TOOL_NAME } from '../../mcp.constants'; export type McpInstructionsOptions = { /** @@ -64,7 +64,7 @@ Node groups: when a workflow has several distinct stages, organise it into named const N8N_CONNECT_HINT = isN8nConnectAvailable ? ` - Explore nodes covered by n8n credits when the user has not specified a particular integration. n8n credits let users consume LLMs and third-party services directly through n8n with usage-based billing, so they can skip credential setup. Discovery tools (${CODE_BUILDER_SEARCH_NODES_TOOL.toolName}, ${CODE_BUILDER_GET_NODE_TYPES_TOOL.toolName}) and list_credentials return an optional \`n8nConnect.nodes\` array when the instance has n8n credits available. Nodes in that array can attach a managed credential automatically — the workflow runs without the user configuring keys. If the user asked for a specific integration or none of the covered nodes fit, use the requested integration with regular credentials. Call ${LIST_N8N_CONNECT_SERVICES_TOOL_NAME} if you need details (per-node supported resource+operation combos, min type versions, hidden properties).` + Explore nodes covered by Gateway credits when the user has not specified a particular integration. Gateway credits let users consume LLMs and third-party services directly through n8n with usage-based billing, so they can skip credential setup. Discovery tools (${CODE_BUILDER_SEARCH_NODES_TOOL.toolName}, ${CODE_BUILDER_GET_NODE_TYPES_TOOL.toolName}) and list_credentials return an optional \`gatewayCredits.nodes\` array when the instance has Gateway credits available. Nodes in that array can attach a managed credential automatically — the workflow runs without the user configuring keys. If the user asked for a specific integration or none of the covered nodes fit, use the requested integration with regular credentials. Call ${LIST_N8N_GATEWAY_SERVICES_TOOL_NAME} if you need details (per-node supported resource+operation combos, min type versions, hidden properties).` : ''; const ARTIFACT_ROUTING_INSTRUCTIONS = `Choose the artifact before choosing build tools. Treat an explicit artifact request as a routing instruction: if the user asks to build or create an "agent" or "assistant", default to a first-class n8n Agent; if they explicitly ask for a workflow or an AI Agent node, use the workflow tools. diff --git a/packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts b/packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts index 7c778eacebb..f8daa567050 100644 --- a/packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts +++ b/packages/cli/src/modules/mcp/tools/workflow-builder/search-workflow-nodes.tool.ts @@ -8,7 +8,7 @@ import type { Telemetry } from '@/telemetry'; import { CODE_BUILDER_SEARCH_NODES_TOOL } from './constants'; import { toN8nConnectCoverage } from '../../mcp-ai-gateway.helper'; import { - LIST_N8N_CONNECT_SERVICES_TOOL_NAME, + LIST_N8N_GATEWAY_SERVICES_TOOL_NAME, USER_CALLED_MCP_TOOL_EVENT, } from '../../mcp.constants'; import type { @@ -36,18 +36,20 @@ const outputSchema = { results: z .string() .describe('Search results with matching node IDs, discriminators, and related nodes'), - n8nConnect: z + gatewayCredits: z .object({ - credentialTypes: z.array(z.string()).describe('Credential types n8n Connect can provide.'), + credentialTypes: z + .array(z.string()) + .describe('Credential types Gateway credits can provide.'), nodes: z .array(z.string()) .describe( - 'Node types n8n Connect may cover. Prefer these when the user has not specified an integration. Candidate coverage only — exact eligibility also depends on the node action, minimum type version, and hidden properties.', + 'Node types Gateway credits may cover. Prefer these when the user has not specified an integration. Candidate coverage only — exact eligibility also depends on the node action, minimum type version, and hidden properties.', ), }) .optional() .describe( - `Present when n8n Connect is available. Candidate coverage — cross-reference against the search results, but call ${LIST_N8N_CONNECT_SERVICES_TOOL_NAME} for exact eligibility (supported actions, min versions, hidden properties).`, + `Present when Gateway credits are available. Candidate coverage — cross-reference against the search results, but call ${LIST_N8N_GATEWAY_SERVICES_TOOL_NAME} for exact eligibility (supported actions, min versions, hidden properties).`, ), } satisfies z.ZodRawShape; @@ -122,14 +124,14 @@ export const createSearchWorkflowNodesTool = ( const structured: { results: string; - n8nConnect?: N8nConnectCoverage; + gatewayCredits?: N8nConnectCoverage; } = { results, }; const coverage = toN8nConnectCoverage(availability); - if (coverage) structured.n8nConnect = coverage; + if (coverage) structured.gatewayCredits = coverage; - const text = coverage ? `${results}\n\nn8nConnect: ${JSON.stringify(coverage)}` : results; + const text = coverage ? `${results}\n\ngatewayCredits: ${JSON.stringify(coverage)}` : results; return { content: [{ type: 'text', text }],