n8n
Version:
n8n Workflow Automation Tool
148 lines • 6.06 kB
JavaScript
"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_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 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'),
error: zod_1.default.string().optional().describe('Error message when the tool failed'),
};
const createListCredentialsTool = (user, credentialsService, telemetry) => ({
name: 'list_credentials',
config: {
description: 'List credentials the current user can access. Use this to find a credential ID before referencing it from a workflow node. 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,
});
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