mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-28 15:43:07 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77048347b3 | ||
|
|
6f695be482 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [2.35.3] - 2026-02-19
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Updated n8n dependencies**: n8n 2.6.3 → 2.8.3, n8n-core 2.6.1 → 2.8.1, n8n-workflow 2.6.0 → 2.8.0, @n8n/n8n-nodes-langchain 2.6.2 → 2.8.1
|
||||||
|
- **Fixed node loader for langchain package**: Adapted node loader to bypass restricted package.json `exports` field in @n8n/n8n-nodes-langchain >=2.9.0, resolving node files via absolute paths instead of `require.resolve()`
|
||||||
|
- **Fixed community doc generation for cloud LLMs**: Added `N8N_MCP_LLM_API_KEY`/`OPENAI_API_KEY` env var support, switched to `max_completion_tokens`, and auto-omit `temperature` for cloud API endpoints
|
||||||
|
- Rebuilt node database with 1,236 nodes (673 from n8n-nodes-base, 133 from @n8n/n8n-nodes-langchain, 430 community)
|
||||||
|
- Refreshed community nodes (361 verified + 69 npm) with 424/430 AI documentation summaries
|
||||||
|
|
||||||
|
Conceived by Romuald Czlonkowski - https://www.aiadvisors.pl/en
|
||||||
|
|
||||||
|
## [2.35.2] - 2026-02-09
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **MCP Apps: Disable non-rendering apps in Claude.ai**: Disabled 3 MCP Apps (workflow-list, execution-history, health-dashboard) that render as collapsed accordions in Claude.ai, and removed `n8n_deploy_template` tool mapping which renders blank content. The server sets `_meta` correctly on the wire but the Claude.ai host ignores it for these tools. The 2 working apps (operation-result for 6 tools, validation-summary for 3 tools) remain active. Disabled apps can be re-enabled once the host-side issue is resolved.
|
||||||
|
|
||||||
|
Conceived by Romuald Czlonkowski - https://www.aiadvisors.pl/en
|
||||||
|
|
||||||
## [2.35.1] - 2026-02-09
|
## [2.35.1] - 2026-02-09
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -18,21 +18,27 @@ npm run update:n8n:check
|
|||||||
# 4. Run update and skip tests (we'll test in CI)
|
# 4. Run update and skip tests (we'll test in CI)
|
||||||
yes y | npm run update:n8n
|
yes y | npm run update:n8n
|
||||||
|
|
||||||
# 5. Create feature branch
|
# 5. Refresh community nodes (standard practice!)
|
||||||
|
npm run fetch:community
|
||||||
|
npm run generate:docs
|
||||||
|
|
||||||
|
# 6. Create feature branch
|
||||||
git checkout -b update/n8n-X.X.X
|
git checkout -b update/n8n-X.X.X
|
||||||
|
|
||||||
# 6. Update version in package.json (must be HIGHER than latest release!)
|
# 7. Update version in package.json (must be HIGHER than latest release!)
|
||||||
# Edit: "version": "2.XX.X" (not the version from the release list!)
|
# Edit: "version": "2.XX.X" (not the version from the release list!)
|
||||||
|
|
||||||
# 7. Update CHANGELOG.md
|
# 8. Update CHANGELOG.md
|
||||||
# - Change version number to match package.json
|
# - Change version number to match package.json
|
||||||
# - Update date to today
|
# - Update date to today
|
||||||
# - Update dependency versions
|
# - Update dependency versions
|
||||||
|
# - Include community node refresh counts
|
||||||
|
|
||||||
# 8. Update README badge
|
# 9. Update README badge and node counts
|
||||||
# Edit line 8: Change n8n version badge to new n8n version
|
# Edit line 8: Change n8n version badge to new n8n version
|
||||||
|
# Update total node count in description (core + community)
|
||||||
|
|
||||||
# 9. Commit and push
|
# 10. Commit and push
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "chore: update n8n to X.X.X and bump version to 2.XX.X
|
git commit -m "chore: update n8n to X.X.X and bump version to 2.XX.X
|
||||||
|
|
||||||
@@ -41,7 +47,8 @@ git commit -m "chore: update n8n to X.X.X and bump version to 2.XX.X
|
|||||||
- Updated n8n-workflow from X.X.X to X.X.X
|
- Updated n8n-workflow from X.X.X to X.X.X
|
||||||
- Updated @n8n/n8n-nodes-langchain from X.X.X to X.X.X
|
- Updated @n8n/n8n-nodes-langchain from X.X.X to X.X.X
|
||||||
- Rebuilt node database with XXX nodes (XXX from n8n-nodes-base, XXX from @n8n/n8n-nodes-langchain)
|
- Rebuilt node database with XXX nodes (XXX from n8n-nodes-base, XXX from @n8n/n8n-nodes-langchain)
|
||||||
- Updated README badge with new n8n version
|
- Refreshed community nodes (XXX verified + XXX npm)
|
||||||
|
- Updated README badge with new n8n version and node counts
|
||||||
- Updated CHANGELOG with dependency changes
|
- Updated CHANGELOG with dependency changes
|
||||||
|
|
||||||
Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en
|
Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en
|
||||||
@@ -52,10 +59,10 @@ Co-Authored-By: Claude <noreply@anthropic.com>"
|
|||||||
|
|
||||||
git push -u origin update/n8n-X.X.X
|
git push -u origin update/n8n-X.X.X
|
||||||
|
|
||||||
# 10. Create PR
|
# 11. Create PR
|
||||||
gh pr create --title "chore: update n8n to X.X.X" --body "Updates n8n and all related dependencies to the latest versions..."
|
gh pr create --title "chore: update n8n to X.X.X" --body "Updates n8n and all related dependencies to the latest versions..."
|
||||||
|
|
||||||
# 11. After PR is merged, verify release triggered
|
# 12. After PR is merged, verify release triggered
|
||||||
gh release list | head -1
|
gh release list | head -1
|
||||||
# If the new version appears, you're done!
|
# If the new version appears, you're done!
|
||||||
# If not, the version might have already been released - bump version again and create new PR
|
# If not, the version might have already been released - bump version again and create new PR
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
[](https://www.npmjs.com/package/n8n-mcp)
|
[](https://www.npmjs.com/package/n8n-mcp)
|
||||||
[](https://codecov.io/gh/czlonkowski/n8n-mcp)
|
[](https://codecov.io/gh/czlonkowski/n8n-mcp)
|
||||||
[](https://github.com/czlonkowski/n8n-mcp/actions)
|
[](https://github.com/czlonkowski/n8n-mcp/actions)
|
||||||
[](https://github.com/n8n-io/n8n)
|
[](https://github.com/n8n-io/n8n)
|
||||||
[](https://github.com/czlonkowski/n8n-mcp/pkgs/container/n8n-mcp)
|
[](https://github.com/czlonkowski/n8n-mcp/pkgs/container/n8n-mcp)
|
||||||
[](https://railway.com/deploy/n8n-mcp?referralCode=n8n-mcp)
|
[](https://railway.com/deploy/n8n-mcp?referralCode=n8n-mcp)
|
||||||
|
|
||||||
A Model Context Protocol (MCP) server that provides AI assistants with comprehensive access to n8n node documentation, properties, and operations. Deploy in minutes to give Claude and other AI assistants deep knowledge about n8n's 1,084 workflow automation nodes (537 core + 547 community).
|
A Model Context Protocol (MCP) server that provides AI assistants with comprehensive access to n8n node documentation, properties, and operations. Deploy in minutes to give Claude and other AI assistants deep knowledge about n8n's 1,236 workflow automation nodes (806 core + 430 community).
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
BIN
data/nodes.db
BIN
data/nodes.db
Binary file not shown.
2
dist/loaders/node-loader.d.ts
vendored
2
dist/loaders/node-loader.d.ts
vendored
@@ -6,6 +6,8 @@ export interface LoadedNode {
|
|||||||
export declare class N8nNodeLoader {
|
export declare class N8nNodeLoader {
|
||||||
private readonly CORE_PACKAGES;
|
private readonly CORE_PACKAGES;
|
||||||
loadAllNodes(): Promise<LoadedNode[]>;
|
loadAllNodes(): Promise<LoadedNode[]>;
|
||||||
|
private resolvePackageDir;
|
||||||
|
private loadNodeModule;
|
||||||
private loadPackageNodes;
|
private loadPackageNodes;
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=node-loader.d.ts.map
|
//# sourceMappingURL=node-loader.d.ts.map
|
||||||
2
dist/loaders/node-loader.d.ts.map
vendored
2
dist/loaders/node-loader.d.ts.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"node-loader.d.ts","sourceRoot":"","sources":["../../src/loaders/node-loader.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG5B;IAEI,YAAY,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YAmB7B,gBAAgB;CAqD/B"}
|
{"version":3,"file":"node-loader.d.ts","sourceRoot":"","sources":["../../src/loaders/node-loader.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG5B;IAEI,YAAY,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAuB3C,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,cAAc;YAIR,gBAAgB;CAuD/B"}
|
||||||
16
dist/loaders/node-loader.js
vendored
16
dist/loaders/node-loader.js
vendored
@@ -28,15 +28,23 @@ class N8nNodeLoader {
|
|||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
resolvePackageDir(packagePath) {
|
||||||
|
const pkgJsonPath = require.resolve(`${packagePath}/package.json`);
|
||||||
|
return path_1.default.dirname(pkgJsonPath);
|
||||||
|
}
|
||||||
|
loadNodeModule(absolutePath) {
|
||||||
|
return require(absolutePath);
|
||||||
|
}
|
||||||
async loadPackageNodes(packageName, packagePath, packageJson) {
|
async loadPackageNodes(packageName, packagePath, packageJson) {
|
||||||
const n8nConfig = packageJson.n8n || {};
|
const n8nConfig = packageJson.n8n || {};
|
||||||
const nodes = [];
|
const nodes = [];
|
||||||
|
const packageDir = this.resolvePackageDir(packagePath);
|
||||||
const nodesList = n8nConfig.nodes || [];
|
const nodesList = n8nConfig.nodes || [];
|
||||||
if (Array.isArray(nodesList)) {
|
if (Array.isArray(nodesList)) {
|
||||||
for (const nodePath of nodesList) {
|
for (const nodePath of nodesList) {
|
||||||
try {
|
try {
|
||||||
const fullPath = require.resolve(`${packagePath}/${nodePath}`);
|
const fullPath = path_1.default.join(packageDir, nodePath);
|
||||||
const nodeModule = require(fullPath);
|
const nodeModule = this.loadNodeModule(fullPath);
|
||||||
const nodeNameMatch = nodePath.match(/\/([^\/]+)\.node\.(js|ts)$/);
|
const nodeNameMatch = nodePath.match(/\/([^\/]+)\.node\.(js|ts)$/);
|
||||||
const nodeName = nodeNameMatch ? nodeNameMatch[1] : path_1.default.basename(nodePath, '.node.js');
|
const nodeName = nodeNameMatch ? nodeNameMatch[1] : path_1.default.basename(nodePath, '.node.js');
|
||||||
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
||||||
@@ -56,8 +64,8 @@ class N8nNodeLoader {
|
|||||||
else {
|
else {
|
||||||
for (const [nodeName, nodePath] of Object.entries(nodesList)) {
|
for (const [nodeName, nodePath] of Object.entries(nodesList)) {
|
||||||
try {
|
try {
|
||||||
const fullPath = require.resolve(`${packagePath}/${nodePath}`);
|
const fullPath = path_1.default.join(packageDir, nodePath);
|
||||||
const nodeModule = require(fullPath);
|
const nodeModule = this.loadNodeModule(fullPath);
|
||||||
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
||||||
if (NodeClass) {
|
if (NodeClass) {
|
||||||
nodes.push({ packageName, nodeName, NodeClass });
|
nodes.push({ packageName, nodeName, NodeClass });
|
||||||
|
|||||||
2
dist/loaders/node-loader.js.map
vendored
2
dist/loaders/node-loader.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"node-loader.js","sourceRoot":"","sources":["../../src/loaders/node-loader.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"node-loader.js","sourceRoot":"","sources":["../../src/loaders/node-loader.ts"],"names":[],"mappings":"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"}
|
||||||
14515
package-lock.json
generated
14515
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-mcp",
|
"name": "n8n-mcp",
|
||||||
"version": "2.35.1",
|
"version": "2.35.3",
|
||||||
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@@ -153,16 +153,16 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "1.20.1",
|
"@modelcontextprotocol/sdk": "1.20.1",
|
||||||
"@n8n/n8n-nodes-langchain": "^2.6.2",
|
"@n8n/n8n-nodes-langchain": "^2.8.1",
|
||||||
"@supabase/supabase-js": "^2.57.4",
|
"@supabase/supabase-js": "^2.57.4",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"express-rate-limit": "^7.1.5",
|
"express-rate-limit": "^7.1.5",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"lru-cache": "^11.2.1",
|
"lru-cache": "^11.2.1",
|
||||||
"n8n": "^2.6.3",
|
"n8n": "^2.8.3",
|
||||||
"n8n-core": "^2.6.1",
|
"n8n-core": "^2.8.1",
|
||||||
"n8n-workflow": "^2.6.0",
|
"n8n-workflow": "^2.8.0",
|
||||||
"openai": "^4.77.0",
|
"openai": "^4.77.0",
|
||||||
"sql.js": "^1.13.0",
|
"sql.js": "^1.13.0",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ export interface DocumentationGeneratorConfig {
|
|||||||
timeout?: number;
|
timeout?: number;
|
||||||
/** Max tokens for response (default: 2000) */
|
/** Max tokens for response (default: 2000) */
|
||||||
maxTokens?: number;
|
maxTokens?: number;
|
||||||
|
/** Temperature for generation (default: 0.3, set to undefined to omit) */
|
||||||
|
temperature?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default configuration
|
* Default configuration
|
||||||
*/
|
*/
|
||||||
const DEFAULT_CONFIG: Required<Omit<DocumentationGeneratorConfig, 'baseUrl'>> = {
|
const DEFAULT_CONFIG: Required<Omit<DocumentationGeneratorConfig, 'baseUrl' | 'temperature'>> = {
|
||||||
model: 'qwen3-4b-thinking-2507',
|
model: 'qwen3-4b-thinking-2507',
|
||||||
apiKey: 'not-needed',
|
apiKey: 'not-needed',
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
@@ -78,6 +80,7 @@ export class DocumentationGenerator {
|
|||||||
private model: string;
|
private model: string;
|
||||||
private maxTokens: number;
|
private maxTokens: number;
|
||||||
private timeout: number;
|
private timeout: number;
|
||||||
|
private temperature?: number;
|
||||||
|
|
||||||
constructor(config: DocumentationGeneratorConfig) {
|
constructor(config: DocumentationGeneratorConfig) {
|
||||||
const fullConfig = { ...DEFAULT_CONFIG, ...config };
|
const fullConfig = { ...DEFAULT_CONFIG, ...config };
|
||||||
@@ -90,6 +93,7 @@ export class DocumentationGenerator {
|
|||||||
this.model = fullConfig.model;
|
this.model = fullConfig.model;
|
||||||
this.maxTokens = fullConfig.maxTokens;
|
this.maxTokens = fullConfig.maxTokens;
|
||||||
this.timeout = fullConfig.timeout;
|
this.timeout = fullConfig.timeout;
|
||||||
|
this.temperature = fullConfig.temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,8 +105,8 @@ export class DocumentationGenerator {
|
|||||||
|
|
||||||
const completion = await this.client.chat.completions.create({
|
const completion = await this.client.chat.completions.create({
|
||||||
model: this.model,
|
model: this.model,
|
||||||
max_tokens: this.maxTokens,
|
max_completion_tokens: this.maxTokens,
|
||||||
temperature: 0.3, // Lower temperature for more consistent output
|
...(this.temperature !== undefined ? { temperature: this.temperature } : {}),
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'system',
|
role: 'system',
|
||||||
@@ -321,7 +325,7 @@ Guidelines:
|
|||||||
try {
|
try {
|
||||||
const completion = await this.client.chat.completions.create({
|
const completion = await this.client.chat.completions.create({
|
||||||
model: this.model,
|
model: this.model,
|
||||||
max_tokens: 10,
|
max_completion_tokens: 200,
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
@@ -353,10 +357,15 @@ export function createDocumentationGenerator(): DocumentationGenerator {
|
|||||||
const baseUrl = process.env.N8N_MCP_LLM_BASE_URL || 'http://localhost:1234/v1';
|
const baseUrl = process.env.N8N_MCP_LLM_BASE_URL || 'http://localhost:1234/v1';
|
||||||
const model = process.env.N8N_MCP_LLM_MODEL || 'qwen3-4b-thinking-2507';
|
const model = process.env.N8N_MCP_LLM_MODEL || 'qwen3-4b-thinking-2507';
|
||||||
const timeout = parseInt(process.env.N8N_MCP_LLM_TIMEOUT || '60000', 10);
|
const timeout = parseInt(process.env.N8N_MCP_LLM_TIMEOUT || '60000', 10);
|
||||||
|
const apiKey = process.env.N8N_MCP_LLM_API_KEY || process.env.OPENAI_API_KEY;
|
||||||
|
// Only set temperature for local LLM servers; cloud APIs like OpenAI may not support custom values
|
||||||
|
const isLocalServer = !baseUrl.includes('openai.com') && !baseUrl.includes('anthropic.com');
|
||||||
|
|
||||||
return new DocumentationGenerator({
|
return new DocumentationGenerator({
|
||||||
baseUrl,
|
baseUrl,
|
||||||
model,
|
model,
|
||||||
timeout,
|
timeout,
|
||||||
|
...(apiKey ? { apiKey } : {}),
|
||||||
|
...(isLocalServer ? { temperature: 0.3 } : {}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,28 @@ export class N8nNodeLoader {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the absolute directory of an installed package.
|
||||||
|
* Uses require.resolve on package.json (always exported) and strips the filename.
|
||||||
|
*/
|
||||||
|
private resolvePackageDir(packagePath: string): string {
|
||||||
|
const pkgJsonPath = require.resolve(`${packagePath}/package.json`);
|
||||||
|
return path.dirname(pkgJsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a node module by absolute file path, bypassing package.json "exports".
|
||||||
|
* Some packages (e.g. @n8n/n8n-nodes-langchain >=2.9) restrict exports but
|
||||||
|
* still list node files in the n8n.nodes array — we need direct filesystem access.
|
||||||
|
*/
|
||||||
|
private loadNodeModule(absolutePath: string): any {
|
||||||
|
return require(absolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
private async loadPackageNodes(packageName: string, packagePath: string, packageJson: any): Promise<LoadedNode[]> {
|
private async loadPackageNodes(packageName: string, packagePath: string, packageJson: any): Promise<LoadedNode[]> {
|
||||||
const n8nConfig = packageJson.n8n || {};
|
const n8nConfig = packageJson.n8n || {};
|
||||||
const nodes: LoadedNode[] = [];
|
const nodes: LoadedNode[] = [];
|
||||||
|
const packageDir = this.resolvePackageDir(packagePath);
|
||||||
|
|
||||||
// Check if nodes is an array or object
|
// Check if nodes is an array or object
|
||||||
const nodesList = n8nConfig.nodes || [];
|
const nodesList = n8nConfig.nodes || [];
|
||||||
@@ -42,8 +61,9 @@ export class N8nNodeLoader {
|
|||||||
// Handle array format (n8n-nodes-base uses this)
|
// Handle array format (n8n-nodes-base uses this)
|
||||||
for (const nodePath of nodesList) {
|
for (const nodePath of nodesList) {
|
||||||
try {
|
try {
|
||||||
const fullPath = require.resolve(`${packagePath}/${nodePath}`);
|
// Resolve absolute path directly to bypass package exports restrictions
|
||||||
const nodeModule = require(fullPath);
|
const fullPath = path.join(packageDir, nodePath);
|
||||||
|
const nodeModule = this.loadNodeModule(fullPath);
|
||||||
|
|
||||||
// Extract node name from path (e.g., "dist/nodes/Slack/Slack.node.js" -> "Slack")
|
// Extract node name from path (e.g., "dist/nodes/Slack/Slack.node.js" -> "Slack")
|
||||||
const nodeNameMatch = nodePath.match(/\/([^\/]+)\.node\.(js|ts)$/);
|
const nodeNameMatch = nodePath.match(/\/([^\/]+)\.node\.(js|ts)$/);
|
||||||
@@ -65,8 +85,8 @@ export class N8nNodeLoader {
|
|||||||
// Handle object format (for other packages)
|
// Handle object format (for other packages)
|
||||||
for (const [nodeName, nodePath] of Object.entries(nodesList)) {
|
for (const [nodeName, nodePath] of Object.entries(nodesList)) {
|
||||||
try {
|
try {
|
||||||
const fullPath = require.resolve(`${packagePath}/${nodePath as string}`);
|
const fullPath = path.join(packageDir, nodePath as string);
|
||||||
const nodeModule = require(fullPath);
|
const nodeModule = this.loadNodeModule(fullPath);
|
||||||
|
|
||||||
// Handle default export and various export patterns
|
// Handle default export and various export patterns
|
||||||
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
const NodeClass = nodeModule.default || nodeModule[nodeName] || Object.values(nodeModule)[0];
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const UI_APP_CONFIGS: UIAppConfig[] = [
|
|||||||
'n8n_delete_workflow',
|
'n8n_delete_workflow',
|
||||||
'n8n_test_workflow',
|
'n8n_test_workflow',
|
||||||
'n8n_autofix_workflow',
|
'n8n_autofix_workflow',
|
||||||
'n8n_deploy_template',
|
// n8n_deploy_template disabled: Claude.ai renders blank content for this tool
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -29,34 +29,8 @@ export const UI_APP_CONFIGS: UIAppConfig[] = [
|
|||||||
'n8n_validate_workflow',
|
'n8n_validate_workflow',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// workflow-list, execution-history, health-dashboard disabled:
|
||||||
id: 'workflow-list',
|
// Claude.ai does not render these apps (shows collapsed accordions).
|
||||||
displayName: 'Workflow List',
|
// The server sets _meta correctly on the wire but the host ignores it.
|
||||||
description: 'Compact table of workflows with status, tags, and metadata',
|
// Re-enable once the host-side issue is resolved.
|
||||||
uri: 'ui://n8n-mcp/workflow-list',
|
|
||||||
mimeType: 'text/html;profile=mcp-app',
|
|
||||||
toolPatterns: [
|
|
||||||
'n8n_list_workflows',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'execution-history',
|
|
||||||
displayName: 'Execution History',
|
|
||||||
description: 'Execution history table with status summary bar',
|
|
||||||
uri: 'ui://n8n-mcp/execution-history',
|
|
||||||
mimeType: 'text/html;profile=mcp-app',
|
|
||||||
toolPatterns: [
|
|
||||||
'n8n_executions',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'health-dashboard',
|
|
||||||
displayName: 'Health Dashboard',
|
|
||||||
description: 'Connection status, versions, and performance metrics',
|
|
||||||
uri: 'ui://n8n-mcp/health-dashboard',
|
|
||||||
mimeType: 'text/html;profile=mcp-app',
|
|
||||||
toolPatterns: [
|
|
||||||
'n8n_health_check',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
* Environment variables:
|
* Environment variables:
|
||||||
* N8N_MCP_LLM_BASE_URL - LLM server URL (default: http://localhost:1234/v1)
|
* N8N_MCP_LLM_BASE_URL - LLM server URL (default: http://localhost:1234/v1)
|
||||||
* N8N_MCP_LLM_MODEL - LLM model name (default: qwen3-4b-thinking-2507)
|
* N8N_MCP_LLM_MODEL - LLM model name (default: qwen3-4b-thinking-2507)
|
||||||
|
* N8N_MCP_LLM_API_KEY - LLM API key (falls back to OPENAI_API_KEY; default: 'not-needed')
|
||||||
* N8N_MCP_LLM_TIMEOUT - Request timeout in ms (default: 60000)
|
* N8N_MCP_LLM_TIMEOUT - Request timeout in ms (default: 60000)
|
||||||
* N8N_MCP_DB_PATH - Database path (default: ./data/nodes.db)
|
* N8N_MCP_DB_PATH - Database path (default: ./data/nodes.db)
|
||||||
*/
|
*/
|
||||||
@@ -81,6 +82,7 @@ Options:
|
|||||||
Environment Variables:
|
Environment Variables:
|
||||||
N8N_MCP_LLM_BASE_URL LLM server URL (default: http://localhost:1234/v1)
|
N8N_MCP_LLM_BASE_URL LLM server URL (default: http://localhost:1234/v1)
|
||||||
N8N_MCP_LLM_MODEL LLM model name (default: qwen3-4b-thinking-2507)
|
N8N_MCP_LLM_MODEL LLM model name (default: qwen3-4b-thinking-2507)
|
||||||
|
N8N_MCP_LLM_API_KEY LLM API key (falls back to OPENAI_API_KEY; default: 'not-needed')
|
||||||
N8N_MCP_LLM_TIMEOUT Request timeout in ms (default: 60000)
|
N8N_MCP_LLM_TIMEOUT Request timeout in ms (default: 60000)
|
||||||
N8N_MCP_DB_PATH Database path (default: ./data/nodes.db)
|
N8N_MCP_DB_PATH Database path (default: ./data/nodes.db)
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ describe('DocumentationGenerator', () => {
|
|||||||
apiKey: 'test-key',
|
apiKey: 'test-key',
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
maxTokens: 1000,
|
maxTokens: 1000,
|
||||||
|
temperature: 0.3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const validSummary = {
|
const validSummary = {
|
||||||
@@ -163,7 +164,7 @@ describe('DocumentationGenerator', () => {
|
|||||||
|
|
||||||
expect(mockCreate).toHaveBeenCalledWith({
|
expect(mockCreate).toHaveBeenCalledWith({
|
||||||
model: 'test-model',
|
model: 'test-model',
|
||||||
max_tokens: 1000,
|
max_completion_tokens: 1000,
|
||||||
temperature: 0.3,
|
temperature: 0.3,
|
||||||
messages: expect.arrayContaining([
|
messages: expect.arrayContaining([
|
||||||
expect.objectContaining({ role: 'system' }),
|
expect.objectContaining({ role: 'system' }),
|
||||||
@@ -680,7 +681,7 @@ describe('DocumentationGenerator', () => {
|
|||||||
|
|
||||||
expect(mockCreate).toHaveBeenCalledWith(
|
expect(mockCreate).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
max_tokens: 10,
|
max_completion_tokens: 200,
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ describe('UI_APP_CONFIGS', () => {
|
|||||||
expect(config!.toolPatterns).toContain('n8n_update_full_workflow');
|
expect(config!.toolPatterns).toContain('n8n_update_full_workflow');
|
||||||
expect(config!.toolPatterns).toContain('n8n_delete_workflow');
|
expect(config!.toolPatterns).toContain('n8n_delete_workflow');
|
||||||
expect(config!.toolPatterns).toContain('n8n_test_workflow');
|
expect(config!.toolPatterns).toContain('n8n_test_workflow');
|
||||||
expect(config!.toolPatterns).toContain('n8n_deploy_template');
|
expect(config!.toolPatterns).not.toContain('n8n_deploy_template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the validation-summary config', () => {
|
it('should contain the validation-summary config', () => {
|
||||||
@@ -98,29 +98,14 @@ describe('UI_APP_CONFIGS', () => {
|
|||||||
expect(config!.toolPatterns).toContain('n8n_validate_workflow');
|
expect(config!.toolPatterns).toContain('n8n_validate_workflow');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have exactly 5 configs', () => {
|
it('should have exactly 2 configs', () => {
|
||||||
expect(UI_APP_CONFIGS.length).toBe(5);
|
expect(UI_APP_CONFIGS.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the workflow-list config', () => {
|
it('should not contain disabled apps', () => {
|
||||||
const config = UI_APP_CONFIGS.find(c => c.id === 'workflow-list');
|
expect(UI_APP_CONFIGS.find(c => c.id === 'workflow-list')).toBeUndefined();
|
||||||
expect(config).toBeDefined();
|
expect(UI_APP_CONFIGS.find(c => c.id === 'execution-history')).toBeUndefined();
|
||||||
expect(config!.displayName).toBe('Workflow List');
|
expect(UI_APP_CONFIGS.find(c => c.id === 'health-dashboard')).toBeUndefined();
|
||||||
expect(config!.toolPatterns).toContain('n8n_list_workflows');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain the execution-history config', () => {
|
|
||||||
const config = UI_APP_CONFIGS.find(c => c.id === 'execution-history');
|
|
||||||
expect(config).toBeDefined();
|
|
||||||
expect(config!.displayName).toBe('Execution History');
|
|
||||||
expect(config!.toolPatterns).toContain('n8n_executions');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain the health-dashboard config', () => {
|
|
||||||
const config = UI_APP_CONFIGS.find(c => c.id === 'health-dashboard');
|
|
||||||
expect(config).toBeDefined();
|
|
||||||
expect(config!.displayName).toBe('Health Dashboard');
|
|
||||||
expect(config!.toolPatterns).toContain('n8n_health_check');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have IDs that are valid URI path segments (no spaces or special chars)', () => {
|
it('should have IDs that are valid URI path segments (no spaces or special chars)', () => {
|
||||||
|
|||||||
@@ -187,8 +187,11 @@ describe('UIAppRegistry', () => {
|
|||||||
expect(UIAppRegistry.getAppForTool('n8n_autofix_workflow')!.config.id).toBe('operation-result');
|
expect(UIAppRegistry.getAppForTool('n8n_autofix_workflow')!.config.id).toBe('operation-result');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should map n8n_deploy_template to operation-result', () => {
|
it('should not map disabled tools', () => {
|
||||||
expect(UIAppRegistry.getAppForTool('n8n_deploy_template')!.config.id).toBe('operation-result');
|
expect(UIAppRegistry.getAppForTool('n8n_deploy_template')).toBeNull();
|
||||||
|
expect(UIAppRegistry.getAppForTool('n8n_list_workflows')).toBeNull();
|
||||||
|
expect(UIAppRegistry.getAppForTool('n8n_executions')).toBeNull();
|
||||||
|
expect(UIAppRegistry.getAppForTool('n8n_health_check')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should map validate_node to validation-summary', () => {
|
it('should map validate_node to validation-summary', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user