UNPKG

n8n

Version:

n8n Workflow Automation Tool

164 lines 7.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createListCredentialsTool = void 0; exports.listCredentials = listCredentials; const zod_1 = __importDefault(require("zod")); const mcp_ai_gateway_helper_1 = require("../mcp-ai-gateway.helper"); const mcp_constants_1 = require("../mcp.constants"); const schemas_1 = require("./schemas"); const MAX_RESULTS = 200; const inputSchema = { limit: (0, schemas_1.createLimitSchema)(MAX_RESULTS), query: zod_1.default.string().optional().describe('Filter credentials by name (partial match)'), type: zod_1.default .string() .optional() .describe('Filter by credential type (e.g. "slackApi", "httpHeaderAuth"). Partial match.'), projectId: zod_1.default .string() .optional() .describe('Restrict results to credentials belonging to this project'), onlySharedWithMe: zod_1.default .boolean() .optional() .describe('Only return credentials shared directly with the current user'), }; const homeProjectSchema = zod_1.default .object({ id: zod_1.default.string().describe('The unique identifier of the project'), name: zod_1.default.string().describe('The name of the project'), type: zod_1.default .string() .describe("The project type. 'personal' is a user's private project; 'team' is a shared project accessible to multiple users."), }) .nullable() .describe('The project that owns the credential, if available'); const n8nConnectSchema = zod_1.default .object({ credentialTypes: zod_1.default .array(zod_1.default.string()) .describe('Credential type names that n8n credits can provide (e.g. "openAiApi").'), nodes: zod_1.default .array(zod_1.default.string()) .describe('Node types covered by n8n 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 ${mcp_constants_1.LIST_N8N_CONNECT_SERVICES_TOOL_NAME} for the authoritative contract.`); const outputSchema = { data: zod_1.default .array(zod_1.default.object({ id: zod_1.default.string().describe('The unique identifier of the credential'), name: zod_1.default.string().describe('The name of the credential'), type: zod_1.default.string().describe('The credential type (e.g. "slackApi")'), scopes: zod_1.default .array(zod_1.default.string()) .describe('The user permissions on this credential (e.g. "credential:read")'), isManaged: zod_1.default .boolean() .describe('Whether the credential is managed by n8n and cannot be edited by the user'), isGlobal: zod_1.default.boolean().describe('Whether the credential is available to all users'), homeProject: homeProjectSchema, })) .describe('List of credentials accessible to the current user'), count: zod_1.default.number().int().min(0).describe('Number of credentials returned'), n8nConnect: n8nConnectSchema, error: zod_1.default.string().optional().describe('Error message when the tool failed'), }; const createListCredentialsTool = (user, credentialsService, telemetry, aiGatewayService) => ({ name: 'list_credentials', config: { description: "List credentials the current user can access. Use this to find a credential ID before referencing it anywhere one is required. Prefer reusing a credential already used by another node in the workflow (get_workflow_details with detailLevel 'full' shows the credentials on each node); when the workflow has none of that type and multiple candidates exist, ask the user which one to use rather than picking one. Never returns credential secret data.", inputSchema, outputSchema, annotations: { title: 'List Credentials', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, }, handler: async ({ limit = MAX_RESULTS, query, type, projectId, onlySharedWithMe = false, }) => { const telemetryPayload = { user_id: user.id, tool_name: 'list_credentials', parameters: { limit, query, type, projectId, onlySharedWithMe }, }; try { const payload = await listCredentials(user, credentialsService, { limit, query, type, projectId, onlySharedWithMe, }); const coverage = (0, mcp_ai_gateway_helper_1.toN8nConnectCoverage)(await aiGatewayService.isAvailable()); if (coverage) payload.n8nConnect = coverage; telemetryPayload.results = { success: true, data: { count: payload.count }, }; telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload); return { content: [{ type: 'text', text: JSON.stringify(payload) }], structuredContent: payload, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); telemetryPayload.results = { success: false, error: errorMessage, }; telemetry.track(mcp_constants_1.USER_CALLED_MCP_TOOL_EVENT, telemetryPayload); const output = { data: [], count: 0, error: errorMessage, }; return { content: [{ type: 'text', text: JSON.stringify(output) }], structuredContent: output, isError: true, }; } }, }); exports.createListCredentialsTool = createListCredentialsTool; async function listCredentials(user, credentialsService, { limit = MAX_RESULTS, query, type, projectId, onlySharedWithMe = false }) { const safeLimit = Math.min(Math.max(1, limit), MAX_RESULTS); const filter = { ...(query ? { name: query } : {}), ...(type ? { type } : {}), ...(projectId ? { projectId } : {}), }; const listQueryOptions = { take: safeLimit, ...(Object.keys(filter ?? {}).length ? { filter } : {}), }; const credentials = await credentialsService.getMany(user, { listQueryOptions, includeScopes: true, includeData: false, includeGlobal: !onlySharedWithMe, onlySharedWithMe, }); const enriched = credentials; const data = enriched.map((c) => ({ id: c.id, name: c.name, type: c.type, scopes: c.scopes ?? [], isManaged: c.isManaged, isGlobal: c.isGlobal, homeProject: c.homeProject ? { id: c.homeProject.id, name: c.homeProject.name, type: c.homeProject.type } : null, })); return { data, count: data.length }; } //# sourceMappingURL=list-credentials.tool.js.map