credentials
Analyze credential requirements for workflows without exposing actual values, generate environment templates, or display setup instructions for secure workflow configuration.
Instructions
Analyze credential requirements for workflows (secure - never exposes actual values)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: analyze requirements, show setup instructions, or generate .env.example |
Input Schema (JSON Schema)
{
"properties": {
"action": {
"description": "Action to perform: analyze requirements, show setup instructions, or generate .env.example",
"enum": [
"analyze",
"instructions",
"generate-env"
],
"type": "string"
}
},
"required": [
"action"
],
"type": "object"
}
Implementation Reference
- src/tools/registry.ts:389-402 (registration)Registers the 'credentials' MCP tool with its name, description, and input schema defining the 'action' parameter.name: 'credentials', description: 'Analyze credential requirements for workflows (secure - never exposes actual values)', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['analyze', 'instructions', 'generate-env'], description: 'Action to perform: analyze requirements, show setup instructions, or generate .env.example', }, }, required: ['action'], }, },
- src/tools/handler.ts:237-249 (handler)ToolHandler.handleTool switch case for 'credentials': dispatches to CredentialHelper methods based on the 'action' input.case 'credentials': const credAction = args?.action as string; switch (credAction) { case 'analyze': return await this.credentialHelper.analyzeCredentialRequirements(); case 'instructions': return await this.credentialHelper.getCredentialSetupInstructions(); case 'generate-env': return await this.credentialHelper.generateSecureEnvExample(); default: throw new Error(`Unknown credential action: ${credAction}`); }
- src/credentials/helper.ts:33-169 (helper)CredentialHelper.analyzeCredentialRequirements(): Scans all workflow files for required credentials, checks .env file for presence, returns detailed analysis report.async analyzeCredentialRequirements(): Promise<any> { try { const flowsDir = path.join(this.workflowsPath, 'flows'); const files = await fs.readdir(flowsDir); const requirements = new Map<string, CredentialRequirement>(); const workflowCredentials = new Map<string, string[]>(); // Analyze each workflow for (const file of files) { if (!file.endsWith('.json') || file.includes('package.json')) continue; const content = await fs.readFile(path.join(flowsDir, file), 'utf-8'); const workflow = JSON.parse(content); const workflowName = file.replace('.json', ''); const credTypes: string[] = []; if (workflow.nodes) { for (const node of workflow.nodes) { // Check for credential requirements if (node.credentials) { Object.keys(node.credentials).forEach(credType => { credTypes.push(credType); // Map credential types to environment variables switch (credType) { case 'openAiApi': requirements.set('OPENAI_API_KEY', { envVar: 'OPENAI_API_KEY', n8nType: 'OpenAI API', displayName: 'OpenAI API Key', instructions: '1. Go to https://platform.openai.com/api-keys\n2. Create a new API key\n3. Add to .env: OPENAI_API_KEY=sk-...', }); break; case 'replicateApi': requirements.set('REPLICATE_API_TOKEN', { envVar: 'REPLICATE_API_TOKEN', n8nType: 'Replicate API', displayName: 'Replicate API Token', instructions: '1. Go to https://replicate.com/account/api-tokens\n2. Create a new token\n3. Add to .env: REPLICATE_API_TOKEN=...', }); break; case 'airtableApi': requirements.set('AIRTABLE_API_KEY', { envVar: 'AIRTABLE_API_KEY', n8nType: 'Airtable API', displayName: 'Airtable API Key or Personal Access Token', instructions: '1. Go to https://airtable.com/create/tokens\n2. Create a personal access token\n3. Add to .env: AIRTABLE_API_KEY=pat...', }); break; case 'slackApi': requirements.set('SLACK_WEBHOOK_URL', { envVar: 'SLACK_WEBHOOK_URL', n8nType: 'Slack Webhook', displayName: 'Slack Webhook URL', instructions: '1. Go to https://api.slack.com/apps\n2. Create an app and add Incoming Webhook\n3. Add to .env: SLACK_WEBHOOK_URL=https://hooks.slack.com/...', }); break; case 'githubApi': requirements.set('GITHUB_TOKEN', { envVar: 'GITHUB_TOKEN', n8nType: 'GitHub API', displayName: 'GitHub Personal Access Token', instructions: '1. Go to https://github.com/settings/tokens\n2. Generate new token (classic)\n3. Add to .env: GITHUB_TOKEN=ghp_...', }); break; } }); } } } if (credTypes.length > 0) { workflowCredentials.set(workflowName, credTypes); } } // Check which credentials exist in .env const envVars = await this.checkEnvFile(); // Format output let output = 'π Credential Requirements Analysis\n\n'; if (requirements.size === 0) { output += 'β No credentials required for these workflows.\n'; } else { output += `π Required Credentials (${requirements.size}):\n\n`; for (const [envVar, req] of requirements) { const hasEnv = envVars.has(envVar); const status = hasEnv ? 'β ' : 'β'; output += `${status} ${req.displayName}\n`; output += ` Environment Variable: ${envVar}\n`; output += ` n8n Credential Type: ${req.n8nType}\n`; if (!hasEnv) { output += ` β οΈ Not found in .env\n`; } output += '\n'; } // Show which workflows need which credentials output += 'π Workflows and Their Credential Requirements:\n\n'; for (const [workflow, creds] of workflowCredentials) { output += `β’ ${workflow}: ${creds.join(', ')}\n`; } // Instructions for missing credentials const missing = Array.from(requirements.entries()).filter(([env]) => !envVars.has(env)); if (missing.length > 0) { output += '\nβ οΈ Missing Credentials Setup Instructions:\n\n'; for (const [, req] of missing) { output += `### ${req.displayName}\n${req.instructions}\n\n`; } output += 'π Security Best Practices:\n'; output += '1. Never commit .env files to git\n'; output += '2. Use strong, unique API keys\n'; output += '3. Rotate keys regularly\n'; output += '4. Limit API key permissions to minimum required\n'; output += '5. Add credentials through n8n UI at http://localhost:5678\n'; } } return { content: [ { type: 'text', text: output, }, ], }; } catch (error: any) { throw new Error(`Failed to analyze credentials: ${error.message}`); } }
- src/credentials/helper.ts:206-248 (helper)CredentialHelper.generateSecureEnvExample(): Generates a secure .env.example file with required credential placeholders and instructions.async generateSecureEnvExample(): Promise<any> { try { const requirements = await this.getRequirementsFromWorkflows(); let content = '# n8n Workflow Credentials\n'; content += '# SECURITY: Never commit this file with real values to git!\n'; content += '# Copy to .env and add your actual API keys\n\n'; content += '# === Required API Credentials ===\n'; content += '# Get these from the respective service providers\n\n'; for (const req of requirements) { content += `# ${req.displayName}\n`; content += `# ${req.instructions.split('\n')[0]}\n`; // First line of instructions content += `${req.envVar}=\n\n`; } content += '# === Security Reminders ===\n'; content += '# 1. Add .env to .gitignore\n'; content += '# 2. Never share or log these values\n'; content += '# 3. Rotate keys regularly\n'; content += '# 4. Use environment-specific keys (dev/prod)\n'; const envExamplePath = path.join(this.workflowsPath, '.env.example'); await fs.writeFile(envExamplePath, content, 'utf-8'); return { content: [ { type: 'text', text: 'β Generated secure .env.example\n\n' + 'π Location: workflows/.env.example\n\n' + 'Next steps:\n' + '1. Copy .env.example to .env\n' + '2. Add your API keys to .env\n' + '3. Never commit .env to git\n' + '4. Add credentials in n8n UI at http://localhost:5678', }, ], }; } catch (error: any) { throw new Error(`Failed to generate .env.example: ${error.message}`); }
- src/credentials/helper.ts:271-326 (helper)CredentialHelper.getCredentialSetupInstructions(): Returns comprehensive step-by-step instructions for securely setting up n8n credentials.async getCredentialSetupInstructions(): Promise<any> { return { content: [ { type: 'text', text: `π Secure Credential Setup for n8n 1οΈβ£ **Prepare Your Credentials** β’ Copy workflows/.env.example to workflows/.env β’ Add your API keys to the .env file β’ Never commit .env to version control 2οΈβ£ **Add Credentials in n8n UI** β’ Open http://localhost:5678 β’ Go to Credentials (left sidebar) β’ Click "Add Credential" β’ Select the credential type β’ Enter your API key/token β’ Save the credential 3οΈβ£ **Link Credentials to Workflows** β’ Open each workflow β’ Click on nodes that need credentials β’ Select the credential from dropdown β’ Save the workflow 4οΈβ£ **Security Best Practices** β Use environment-specific credentials (dev/staging/prod) β Rotate API keys regularly β Use minimal required permissions β Enable 2FA where available β Monitor API usage for anomalies β Never log or print credentials β Never commit credentials to git β Never share credentials in messages 5οΈβ£ **Troubleshooting** β’ If a workflow fails with "Credentials not found": - Check the credential exists in n8n - Verify the credential name matches - Ensure the credential has correct permissions β’ If API calls fail: - Test credentials directly with the service - Check rate limits - Verify API endpoint URLs For detailed setup per service: β’ OpenAI: https://platform.openai.com/docs/api-reference/authentication β’ GitHub: https://docs.github.com/en/authentication β’ Slack: https://api.slack.com/authentication β’ Airtable: https://airtable.com/developers/web/api/authentication`, }, ], }; }