@vinkius-core/mcp-fusion-n8n 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/N8nClient.d.ts +24 -0
- package/dist/N8nClient.d.ts.map +1 -0
- package/dist/N8nClient.js +79 -0
- package/dist/N8nClient.js.map +1 -0
- package/dist/SchemaInferrer.d.ts +12 -0
- package/dist/SchemaInferrer.d.ts.map +1 -0
- package/dist/SchemaInferrer.js +48 -0
- package/dist/SchemaInferrer.js.map +1 -0
- package/dist/ToolSynthesizer.d.ts +43 -0
- package/dist/ToolSynthesizer.d.ts.map +1 -0
- package/dist/ToolSynthesizer.js +92 -0
- package/dist/ToolSynthesizer.js.map +1 -0
- package/dist/WorkflowDiscovery.d.ts +30 -0
- package/dist/WorkflowDiscovery.d.ts.map +1 -0
- package/dist/WorkflowDiscovery.js +95 -0
- package/dist/WorkflowDiscovery.js.map +1 -0
- package/dist/createN8nConnector.d.ts +37 -0
- package/dist/createN8nConnector.d.ts.map +1 -0
- package/dist/createN8nConnector.js +84 -0
- package/dist/createN8nConnector.js.map +1 -0
- package/dist/defineN8nTool.d.ts +26 -0
- package/dist/defineN8nTool.d.ts.map +1 -0
- package/dist/defineN8nTool.js +84 -0
- package/dist/defineN8nTool.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @vinkius-core/mcp-fusion-n8n
|
|
2
|
+
|
|
3
|
+
A bidirectional translation driver: **n8n REST API ↔ MCP In-Memory Objects**.
|
|
4
|
+
|
|
5
|
+
Install this package and you gain **5 engineering primitives** that turn your entire n8n automation infrastructure into AI-native tools.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
const n8n = await createN8nConnector({
|
|
9
|
+
url: process.env.N8N_URL!,
|
|
10
|
+
apiKey: process.env.N8N_API_KEY!,
|
|
11
|
+
includeTags: ['ai-enabled'],
|
|
12
|
+
pollInterval: 60_000,
|
|
13
|
+
onChange: () => server.notification({ method: 'notifications/tools/list_changed' }),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
for (const tool of n8n.tools()) {
|
|
17
|
+
registry.register(defineTool(tool.name, tool.config));
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## The 5 Primitives
|
|
22
|
+
|
|
23
|
+
### 1. Dynamic Ingestion & Zero-Trust Topology
|
|
24
|
+
Connects to n8n at boot (`GET /api/v1/workflows`), scans the visual infrastructure, fetches only active webhook-triggered flows with release tags, and compiles them into `ToolBuilder` instances.
|
|
25
|
+
|
|
26
|
+
**The impact:** The developer writes zero `fetch()` calls. In 3 lines, 400 legacy automations (Jira, Slack, SAP) become native tools for Claude. Tag filtering guarantees the AI never accesses unauthorized internal flows.
|
|
27
|
+
|
|
28
|
+
### 2. Semantic Inference — The Hallucination Cure
|
|
29
|
+
n8n webhooks accept any loose JSON. The package extracts the **Notes** field from the workflow canvas and injects it as the tool `description`.
|
|
30
|
+
|
|
31
|
+
**The impact:** The ops team writes *"Send 'customer_email' and 'urgency' in the body"* in n8n. The AI reads it, understands the semantics, and builds correct JSON with **deterministic precision in zero-shot** — bypassing n8n's complete lack of strict typing.
|
|
32
|
+
|
|
33
|
+
### 3. Real-Time MVA Interception — The SOC2 Shield
|
|
34
|
+
The package produces `ToolBuilder` instances, not a server. You attach Presenters (Zod Egress Firewall) and auth Middleware to sensitive routes — **in RAM, before the port opens**.
|
|
35
|
+
|
|
36
|
+
**The impact:** n8n returns 2MB of raw Salesforce JSON packed with internal IPs and passwords. Your Zod Presenter strips every sensitive key. The LLM receives 5KB of clean data. **Absolute data governance.**
|
|
37
|
+
|
|
38
|
+
### 4. Surgical Construction — `defineN8nTool()`
|
|
39
|
+
For critical routes (Stripe refunds, production deploys), `defineN8nTool()` points to the exact workflow ID, enforces hand-written input schemas, and attaches authorization middleware.
|
|
40
|
+
|
|
41
|
+
**The impact:** n8n is "dumb muscle". The business rules, strict typing, and security stay **hardcoded in your TypeScript backend**.
|
|
42
|
+
|
|
43
|
+
### 5. Live State Sync — Infrastructure Hot-Reload
|
|
44
|
+
Background polling motor monitors n8n every N seconds. On change, recompiles `ToolBuilder` in RAM and fires `notifications/tools/list_changed`.
|
|
45
|
+
|
|
46
|
+
**The impact:** Ops activates a new workflow on Friday at 3 PM. Within 60 seconds, Claude has it — without restarting the Node.js server. **Zero-downtime.**
|
|
47
|
+
|
|
48
|
+
## What You Deliver
|
|
49
|
+
|
|
50
|
+
A **fiber-optic cable** between the low-code world (n8n) and the pro-code world (**MCP Fusion**). The package resolves HTTP I/O, route discovery, state synchronization, and LLM semantics. But it returns **100% of the control** over Routing, Protocol, and Security (MVA) to the developer in `server.ts`.
|
|
51
|
+
|
|
52
|
+
The perfect balance between the insane agility of low-code integrations and hardcore software engineering.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install @vinkius-core/mcp-fusion-n8n @vinkius-core/mcp-fusion zod
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Documentation
|
|
61
|
+
|
|
62
|
+
Full docs with configuration reference and production examples: [mcp-fusion.vinkius.com/n8n-connector](https://mcp-fusion.vinkius.com/n8n-connector).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { N8nWorkflow, N8nWebhookResponse } from './types.js';
|
|
2
|
+
export interface N8nClientConfig {
|
|
3
|
+
readonly url: string;
|
|
4
|
+
readonly apiKey: string;
|
|
5
|
+
readonly timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Minimal HTTP client for the n8n REST API.
|
|
9
|
+
* Handles authentication, URL normalization, and error wrapping.
|
|
10
|
+
*/
|
|
11
|
+
export declare class N8nClient {
|
|
12
|
+
private readonly baseUrl;
|
|
13
|
+
private readonly apiKey;
|
|
14
|
+
private readonly timeout;
|
|
15
|
+
constructor(config: N8nClientConfig);
|
|
16
|
+
/** Fetch all active workflows from n8n */
|
|
17
|
+
listWorkflows(): Promise<N8nWorkflow[]>;
|
|
18
|
+
/** Fetch a specific workflow by ID */
|
|
19
|
+
getWorkflow(id: number): Promise<N8nWorkflow>;
|
|
20
|
+
/** Call a webhook endpoint on the n8n instance */
|
|
21
|
+
callWebhook(path: string, method: string, payload?: Record<string, unknown>): Promise<N8nWebhookResponse>;
|
|
22
|
+
private get;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=N8nClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"N8nClient.d.ts","sourceRoot":"","sources":["../src/N8nClient.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,eAAe;IAQnC,0CAA0C;IACpC,aAAa,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAM7C,sCAAsC;IAChC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAOnD,kDAAkD;IAC5C,WAAW,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,kBAAkB,CAAC;YAgChB,GAAG;CAyBpB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// N8nClient — HTTP client for the n8n REST API
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Minimal HTTP client for the n8n REST API.
|
|
6
|
+
* Handles authentication, URL normalization, and error wrapping.
|
|
7
|
+
*/
|
|
8
|
+
export class N8nClient {
|
|
9
|
+
baseUrl;
|
|
10
|
+
apiKey;
|
|
11
|
+
timeout;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.baseUrl = config.url.replace(/\/+$/, '');
|
|
14
|
+
this.apiKey = config.apiKey;
|
|
15
|
+
this.timeout = config.timeout ?? 30_000;
|
|
16
|
+
}
|
|
17
|
+
// ── Workflow Discovery ──
|
|
18
|
+
/** Fetch all active workflows from n8n */
|
|
19
|
+
async listWorkflows() {
|
|
20
|
+
const response = await this.get('/api/v1/workflows?active=true');
|
|
21
|
+
const body = await response.json();
|
|
22
|
+
return body.data;
|
|
23
|
+
}
|
|
24
|
+
/** Fetch a specific workflow by ID */
|
|
25
|
+
async getWorkflow(id) {
|
|
26
|
+
const response = await this.get(`/api/v1/workflows/${id}`);
|
|
27
|
+
return await response.json();
|
|
28
|
+
}
|
|
29
|
+
// ── Webhook Execution ──
|
|
30
|
+
/** Call a webhook endpoint on the n8n instance */
|
|
31
|
+
async callWebhook(path, method, payload) {
|
|
32
|
+
const webhookUrl = `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
35
|
+
try {
|
|
36
|
+
const upperMethod = method.toUpperCase();
|
|
37
|
+
const hasBody = upperMethod !== 'GET' && upperMethod !== 'HEAD';
|
|
38
|
+
const response = await fetch(webhookUrl, {
|
|
39
|
+
method: upperMethod,
|
|
40
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41
|
+
...(hasBody ? { body: JSON.stringify(payload ?? {}) } : {}),
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
});
|
|
44
|
+
const data = await response.json().catch(() => null);
|
|
45
|
+
const execId = response.headers.get('x-n8n-execution-id');
|
|
46
|
+
return {
|
|
47
|
+
status: response.status,
|
|
48
|
+
data,
|
|
49
|
+
...(execId ? { executionId: execId } : {}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// ── Internal ──
|
|
57
|
+
async get(path) {
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
62
|
+
method: 'GET',
|
|
63
|
+
headers: {
|
|
64
|
+
'X-N8N-API-KEY': this.apiKey,
|
|
65
|
+
'Accept': 'application/json',
|
|
66
|
+
},
|
|
67
|
+
signal: controller.signal,
|
|
68
|
+
});
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`n8n API error: ${response.status} ${response.statusText} — ${path}`);
|
|
71
|
+
}
|
|
72
|
+
return response;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=N8nClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"N8nClient.js","sourceRoot":"","sources":["../src/N8nClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ZodTypeAny } from 'zod';
|
|
2
|
+
import type { WebhookConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Infers Zod schemas from n8n webhook configurations.
|
|
5
|
+
*
|
|
6
|
+
* Strategy:
|
|
7
|
+
* - Query parameters → strict Zod fields with type coercion
|
|
8
|
+
* - Request body → `z.record(z.any())` fallback (n8n webhooks accept any JSON)
|
|
9
|
+
* - Workflow notes → `.describe()` on the schema for LLM semantic understanding
|
|
10
|
+
*/
|
|
11
|
+
export declare function inferSchema(config: WebhookConfig): Record<string, ZodTypeAny>;
|
|
12
|
+
//# sourceMappingURL=SchemaInferrer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaInferrer.d.ts","sourceRoot":"","sources":["../src/SchemaInferrer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAK,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAmB7E"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// SchemaInferrer — WebhookConfig → Zod schema for MCP Fusion tools
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/**
|
|
6
|
+
* Infers Zod schemas from n8n webhook configurations.
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* - Query parameters → strict Zod fields with type coercion
|
|
10
|
+
* - Request body → `z.record(z.any())` fallback (n8n webhooks accept any JSON)
|
|
11
|
+
* - Workflow notes → `.describe()` on the schema for LLM semantic understanding
|
|
12
|
+
*/
|
|
13
|
+
export function inferSchema(config) {
|
|
14
|
+
const fields = {};
|
|
15
|
+
// ── Query parameters → strict Zod fields ──
|
|
16
|
+
for (const param of config.queryParams) {
|
|
17
|
+
const field = buildParamField(param.type, param.required);
|
|
18
|
+
fields[param.name] = field;
|
|
19
|
+
}
|
|
20
|
+
// ── Body → open record (n8n webhooks accept arbitrary JSON) ──
|
|
21
|
+
// Only add for methods that accept a body
|
|
22
|
+
const method = config.method.toUpperCase();
|
|
23
|
+
if (method !== 'GET' && method !== 'HEAD' && method !== 'DELETE') {
|
|
24
|
+
fields['body'] = z.record(z.any())
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Request body — see workflow description for expected fields');
|
|
27
|
+
}
|
|
28
|
+
return fields;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build a Zod field for a query parameter with correct type coercion.
|
|
32
|
+
*/
|
|
33
|
+
function buildParamField(type, required) {
|
|
34
|
+
let field;
|
|
35
|
+
switch (type) {
|
|
36
|
+
case 'number':
|
|
37
|
+
field = z.coerce.number();
|
|
38
|
+
break;
|
|
39
|
+
case 'boolean':
|
|
40
|
+
field = z.coerce.boolean();
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
field = z.string();
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
return required ? field : field.optional();
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=SchemaInferrer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaInferrer.js","sourceRoot":"","sources":["../src/SchemaInferrer.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,+EAA+E;AAE/E,OAAO,EAAE,CAAC,EAAmB,MAAM,KAAK,CAAC;AAGzC;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC7C,MAAM,MAAM,GAA+B,EAAE,CAAC;IAE9C,6CAA6C;IAC7C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED,gEAAgE;IAChE,0CAA0C;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;aAC7B,QAAQ,EAAE;aACV,QAAQ,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAY,EAAE,QAAiB;IACpD,IAAI,KAAiB,CAAC;IAEtB,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,QAAQ;YACT,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1B,MAAM;QACV,KAAK,SAAS;YACV,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM;QACV;YACI,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM;IACd,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { WebhookConfig } from './types.js';
|
|
2
|
+
import type { N8nClient } from './N8nClient.js';
|
|
3
|
+
/**
|
|
4
|
+
* Synthesizes MCP Fusion tool definitions from discovered n8n webhook workflows.
|
|
5
|
+
*
|
|
6
|
+
* Uses `defineTool()` pattern — returns config objects that the consumer
|
|
7
|
+
* feeds to their own ToolRegistry. This is the IoC boundary:
|
|
8
|
+
* we produce builders, the developer owns the server.
|
|
9
|
+
*/
|
|
10
|
+
export interface SynthesizedTool {
|
|
11
|
+
/** Tool name (snake_case from workflow name) */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** Full tool config for defineTool() */
|
|
14
|
+
readonly config: {
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly tags: readonly string[];
|
|
17
|
+
readonly actions: Record<string, SynthesizedAction>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface SynthesizedAction {
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly params: Record<string, unknown>;
|
|
23
|
+
readonly handler: (ctx: unknown, args: Record<string, unknown>) => Promise<unknown>;
|
|
24
|
+
readonly annotations?: {
|
|
25
|
+
readonly readOnlyHint?: boolean;
|
|
26
|
+
readonly destructiveHint?: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert a workflow name to a valid snake_case tool name.
|
|
31
|
+
* "Lead Enrichment" → "lead_enrichment"
|
|
32
|
+
* "My Awesome Workflow (v2)" → "my_awesome_workflow_v2"
|
|
33
|
+
*/
|
|
34
|
+
export declare function toToolName(workflowName: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Synthesize a MCP Fusion tool definition from a webhook config.
|
|
37
|
+
*/
|
|
38
|
+
export declare function synthesizeTool(webhook: WebhookConfig, client: N8nClient): SynthesizedTool;
|
|
39
|
+
/**
|
|
40
|
+
* Synthesize tools from an array of webhook configs.
|
|
41
|
+
*/
|
|
42
|
+
export declare function synthesizeAll(webhooks: WebhookConfig[], client: N8nClient): SynthesizedTool[];
|
|
43
|
+
//# sourceMappingURL=ToolSynthesizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolSynthesizer.d.ts","sourceRoot":"","sources":["../src/ToolSynthesizer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE;QACb,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;KACvD,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE;QACnB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;KACtC,CAAC;CACL;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC1B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,SAAS,GAClB,eAAe,CAsEjB;AAED;;GAEG;AACH,wBAAgB,aAAa,CACzB,QAAQ,EAAE,aAAa,EAAE,EACzB,MAAM,EAAE,SAAS,GAClB,eAAe,EAAE,CAEnB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// ToolSynthesizer — WebhookConfig → MCP Fusion ToolBuilder
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { inferSchema } from './SchemaInferrer.js';
|
|
6
|
+
/**
|
|
7
|
+
* Convert a workflow name to a valid snake_case tool name.
|
|
8
|
+
* "Lead Enrichment" → "lead_enrichment"
|
|
9
|
+
* "My Awesome Workflow (v2)" → "my_awesome_workflow_v2"
|
|
10
|
+
*/
|
|
11
|
+
export function toToolName(workflowName) {
|
|
12
|
+
return workflowName
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
15
|
+
.replace(/^_+|_+$/g, '');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Synthesize a MCP Fusion tool definition from a webhook config.
|
|
19
|
+
*/
|
|
20
|
+
export function synthesizeTool(webhook, client) {
|
|
21
|
+
const name = toToolName(webhook.workflowName);
|
|
22
|
+
const schema = inferSchema(webhook);
|
|
23
|
+
const method = webhook.method.toUpperCase();
|
|
24
|
+
const isReadOnly = method === 'GET';
|
|
25
|
+
// Build param definitions from inferred schema
|
|
26
|
+
const params = {};
|
|
27
|
+
for (const [key, zodType] of Object.entries(schema)) {
|
|
28
|
+
if (key === 'body') {
|
|
29
|
+
params[key] = { type: 'object', description: 'Request body — see workflow description for expected fields' };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
params[key] = 'string'; // query params are strings by default
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Build the handler — calls the n8n webhook
|
|
36
|
+
const handler = async (_ctx, args) => {
|
|
37
|
+
const { body, ...queryArgs } = args;
|
|
38
|
+
const payload = body ?? queryArgs;
|
|
39
|
+
const response = await client.callWebhook(webhook.path, webhook.method, payload);
|
|
40
|
+
if (response.status >= 400) {
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
content: [{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `n8n workflow error (HTTP ${response.status}): ${JSON.stringify(response.data)}`,
|
|
46
|
+
}],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
content: [{
|
|
51
|
+
type: 'text',
|
|
52
|
+
text: JSON.stringify(response.data, null, 2),
|
|
53
|
+
}],
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
// Tool description with n8n metadata
|
|
57
|
+
const lines = [
|
|
58
|
+
`[n8n Workflow #${webhook.workflowId}] ${webhook.workflowName}`,
|
|
59
|
+
'',
|
|
60
|
+
webhook.description,
|
|
61
|
+
'',
|
|
62
|
+
`Webhook: ${method} ${webhook.path}`,
|
|
63
|
+
];
|
|
64
|
+
if (webhook.tags.length > 0) {
|
|
65
|
+
lines.push(`Tags: ${webhook.tags.join(', ')}`);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
name,
|
|
69
|
+
config: {
|
|
70
|
+
description: lines.join('\n'),
|
|
71
|
+
tags: [...webhook.tags],
|
|
72
|
+
actions: {
|
|
73
|
+
execute: {
|
|
74
|
+
description: `Execute the "${webhook.workflowName}" workflow`,
|
|
75
|
+
params,
|
|
76
|
+
handler,
|
|
77
|
+
annotations: {
|
|
78
|
+
readOnlyHint: isReadOnly,
|
|
79
|
+
...(isReadOnly ? {} : { destructiveHint: false }),
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Synthesize tools from an array of webhook configs.
|
|
88
|
+
*/
|
|
89
|
+
export function synthesizeAll(webhooks, client) {
|
|
90
|
+
return webhooks.map(w => synthesizeTool(w, client));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=ToolSynthesizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolSynthesizer.js","sourceRoot":"","sources":["../src/ToolSynthesizer.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2DAA2D;AAC3D,+EAA+E;AAE/E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA8BlD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB;IAC3C,OAAO,YAAY;SACd,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC1B,OAAsB,EACtB,MAAiB;IAEjB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,KAAK,KAAK,CAAC;IAEpC,+CAA+C;IAC/C,MAAM,MAAM,GAAoE,EAAE,CAAC;IACnF,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE,CAAC;QACjH,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,sCAAsC;QAClE,CAAC;IACL,CAAC;IAED,4CAA4C;IAC5C,MAAM,OAAO,GAAG,KAAK,EAAE,IAAa,EAAE,IAA6B,EAAE,EAAE;QACnE,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC;QACpC,MAAM,OAAO,GAAI,IAAgC,IAAI,SAAS,CAAC;QAC/D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEjF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACzB,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,4BAA4B,QAAQ,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;qBACzF,CAAC;aACL,CAAC;QACN,CAAC;QAED,OAAO;YACH,OAAO,EAAE,CAAC;oBACN,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC/C,CAAC;SACL,CAAC;IACN,CAAC,CAAC;IAEF,qCAAqC;IACrC,MAAM,KAAK,GAAG;QACV,kBAAkB,OAAO,CAAC,UAAU,KAAK,OAAO,CAAC,YAAY,EAAE;QAC/D,EAAE;QACF,OAAO,CAAC,WAAW;QACnB,EAAE;QACF,YAAY,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE;KACvC,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO;QACH,IAAI;QACJ,MAAM,EAAE;YACJ,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7B,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YACvB,OAAO,EAAE;gBACL,OAAO,EAAE;oBACL,WAAW,EAAE,gBAAgB,OAAO,CAAC,YAAY,YAAY;oBAC7D,MAAM;oBACN,OAAO;oBACP,WAAW,EAAE;wBACT,YAAY,EAAE,UAAU;wBACxB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;qBACpD;iBACJ;aACJ;SACJ;KACJ,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CACzB,QAAyB,EACzB,MAAiB;IAEjB,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { N8nClient } from './N8nClient.js';
|
|
2
|
+
import type { WebhookConfig } from './types.js';
|
|
3
|
+
export interface DiscoveryOptions {
|
|
4
|
+
readonly includeTags?: readonly string[];
|
|
5
|
+
readonly excludeTags?: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Discovers webhook-triggered workflows from an n8n instance.
|
|
9
|
+
*
|
|
10
|
+
* Only workflows with a Webhook node as trigger are included.
|
|
11
|
+
* Tag filtering (include/exclude) is applied after discovery.
|
|
12
|
+
*/
|
|
13
|
+
export declare class WorkflowDiscovery {
|
|
14
|
+
private readonly client;
|
|
15
|
+
private readonly options;
|
|
16
|
+
constructor(client: N8nClient, options?: DiscoveryOptions);
|
|
17
|
+
/** Discover all webhook workflows, apply tag filters, return configs */
|
|
18
|
+
discover(): Promise<WebhookConfig[]>;
|
|
19
|
+
/** Check if a workflow has a Webhook node as its trigger */
|
|
20
|
+
private hasWebhookTrigger;
|
|
21
|
+
/** Find the first webhook node in a workflow */
|
|
22
|
+
private findWebhookNode;
|
|
23
|
+
/** Apply include/exclude tag filters */
|
|
24
|
+
private applyTagFilters;
|
|
25
|
+
/** Extract webhook configuration from a workflow */
|
|
26
|
+
private extractWebhookConfig;
|
|
27
|
+
/** Extract query parameters from webhook node configuration */
|
|
28
|
+
private extractQueryParams;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=WorkflowDiscovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowDiscovery.d.ts","sourceRoot":"","sources":["../src/WorkflowDiscovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAwB,aAAa,EAAc,MAAM,YAAY,CAAC;AAElF,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;GAKG;AACH,qBAAa,iBAAiB;IAEtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,gBAAqB;IAGnD,wEAAwE;IAClE,QAAQ,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAS1C,4DAA4D;IAC5D,OAAO,CAAC,iBAAiB;IAOzB,gDAAgD;IAChD,OAAO,CAAC,eAAe;IAOvB,wCAAwC;IACxC,OAAO,CAAC,eAAe;IAkBvB,oDAAoD;IACpD,OAAO,CAAC,oBAAoB;IAgC5B,+DAA+D;IAC/D,OAAO,CAAC,kBAAkB;CAiB7B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// WorkflowDiscovery — Fetch + filter webhook-triggered workflows
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Discovers webhook-triggered workflows from an n8n instance.
|
|
6
|
+
*
|
|
7
|
+
* Only workflows with a Webhook node as trigger are included.
|
|
8
|
+
* Tag filtering (include/exclude) is applied after discovery.
|
|
9
|
+
*/
|
|
10
|
+
export class WorkflowDiscovery {
|
|
11
|
+
client;
|
|
12
|
+
options;
|
|
13
|
+
constructor(client, options = {}) {
|
|
14
|
+
this.client = client;
|
|
15
|
+
this.options = options;
|
|
16
|
+
}
|
|
17
|
+
/** Discover all webhook workflows, apply tag filters, return configs */
|
|
18
|
+
async discover() {
|
|
19
|
+
const workflows = await this.client.listWorkflows();
|
|
20
|
+
const webhookWorkflows = workflows.filter(w => this.hasWebhookTrigger(w));
|
|
21
|
+
const filtered = this.applyTagFilters(webhookWorkflows);
|
|
22
|
+
return filtered.map(w => this.extractWebhookConfig(w));
|
|
23
|
+
}
|
|
24
|
+
// ── Internal ──
|
|
25
|
+
/** Check if a workflow has a Webhook node as its trigger */
|
|
26
|
+
hasWebhookTrigger(workflow) {
|
|
27
|
+
return workflow.nodes.some(node => node.type === 'n8n-nodes-base.webhook'
|
|
28
|
+
|| node.type === '@n8n/n8n-nodes-base.webhook');
|
|
29
|
+
}
|
|
30
|
+
/** Find the first webhook node in a workflow */
|
|
31
|
+
findWebhookNode(workflow) {
|
|
32
|
+
return workflow.nodes.find(node => node.type === 'n8n-nodes-base.webhook'
|
|
33
|
+
|| node.type === '@n8n/n8n-nodes-base.webhook');
|
|
34
|
+
}
|
|
35
|
+
/** Apply include/exclude tag filters */
|
|
36
|
+
applyTagFilters(workflows) {
|
|
37
|
+
const { includeTags, excludeTags } = this.options;
|
|
38
|
+
return workflows.filter(w => {
|
|
39
|
+
const tags = w.tags.map(t => t.name);
|
|
40
|
+
if (includeTags && includeTags.length > 0) {
|
|
41
|
+
if (!tags.some(t => includeTags.includes(t)))
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (excludeTags && excludeTags.length > 0) {
|
|
45
|
+
if (tags.some(t => excludeTags.includes(t)))
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Extract webhook configuration from a workflow */
|
|
52
|
+
extractWebhookConfig(workflow) {
|
|
53
|
+
const node = this.findWebhookNode(workflow);
|
|
54
|
+
const params = node.parameters;
|
|
55
|
+
// Extract webhook path (n8n stores it as 'path' parameter)
|
|
56
|
+
const path = typeof params['path'] === 'string'
|
|
57
|
+
? `/webhook/${params['path']}`
|
|
58
|
+
: `/webhook/${workflow.id}`;
|
|
59
|
+
// Extract HTTP method (default POST)
|
|
60
|
+
const method = typeof params['httpMethod'] === 'string'
|
|
61
|
+
? params['httpMethod']
|
|
62
|
+
: 'POST';
|
|
63
|
+
// Extract description from workflow notes (the "Hack Semântico")
|
|
64
|
+
const description = workflow.meta?.notes
|
|
65
|
+
?? `n8n Workflow #${workflow.id}: ${workflow.name}`;
|
|
66
|
+
// Extract query parameters if configured
|
|
67
|
+
const queryParams = this.extractQueryParams(params);
|
|
68
|
+
return {
|
|
69
|
+
workflowId: workflow.id,
|
|
70
|
+
workflowName: workflow.name,
|
|
71
|
+
path,
|
|
72
|
+
method,
|
|
73
|
+
description,
|
|
74
|
+
tags: workflow.tags.map(t => t.name),
|
|
75
|
+
queryParams,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Extract query parameters from webhook node configuration */
|
|
79
|
+
extractQueryParams(params) {
|
|
80
|
+
// n8n stores query params in 'options.queryParameterAuthentication'
|
|
81
|
+
// or as configured in the webhook node options
|
|
82
|
+
const options = params['options'];
|
|
83
|
+
if (!options)
|
|
84
|
+
return [];
|
|
85
|
+
const rawParams = options['queryParameters'];
|
|
86
|
+
if (!rawParams || !Array.isArray(rawParams))
|
|
87
|
+
return [];
|
|
88
|
+
return rawParams.map(p => ({
|
|
89
|
+
name: p.name,
|
|
90
|
+
type: p.type || 'string',
|
|
91
|
+
required: p.required ?? false,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=WorkflowDiscovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowDiscovery.js","sourceRoot":"","sources":["../src/WorkflowDiscovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { N8nClient } from './N8nClient.js';
|
|
2
|
+
import { type SynthesizedTool } from './ToolSynthesizer.js';
|
|
3
|
+
import type { N8nConnectorConfig, WebhookConfig } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The n8n connector — auto-discovers webhook workflows and produces
|
|
6
|
+
* tool definitions ready for MCP Fusion's `defineTool()`.
|
|
7
|
+
*
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const n8n = await createN8nConnector({
|
|
10
|
+
* url: '...', apiKey: '...',
|
|
11
|
+
* pollInterval: 60_000,
|
|
12
|
+
* onChange: () => server.notification({ method: 'notifications/tools/list_changed' }),
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export interface N8nConnector {
|
|
17
|
+
/** The HTTP client for n8n API — expose in context if needed */
|
|
18
|
+
readonly client: N8nClient;
|
|
19
|
+
/** Discovered webhook workflow metadata */
|
|
20
|
+
readonly workflows: readonly WebhookConfig[];
|
|
21
|
+
/** Pre-synthesized tool definitions ready for defineTool() */
|
|
22
|
+
tools(): readonly SynthesizedTool[];
|
|
23
|
+
/** Re-discover workflows (manual poll) */
|
|
24
|
+
refresh(): Promise<boolean>;
|
|
25
|
+
/** Stop the background polling loop (if active) */
|
|
26
|
+
stop(): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create an n8n connector that auto-discovers webhook workflows.
|
|
30
|
+
*
|
|
31
|
+
* If `pollInterval` is set, starts a background polling loop that
|
|
32
|
+
* re-discovers workflows and calls `onChange()` when the tool list changes.
|
|
33
|
+
* This enables zero-downtime hot-reload: the MCP server emits
|
|
34
|
+
* `notifications/tools/list_changed` and Claude refreshes instantly.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createN8nConnector(config: N8nConnectorConfig): Promise<N8nConnector>;
|
|
37
|
+
//# sourceMappingURL=createN8nConnector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createN8nConnector.d.ts","sourceRoot":"","sources":["../src/createN8nConnector.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAwB,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IACzB,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,8DAA8D;IAC9D,KAAK,IAAI,SAAS,eAAe,EAAE,CAAC;IACpC,0CAA0C;IAC1C,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,mDAAmD;IACnD,IAAI,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACpC,MAAM,EAAE,kBAAkB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAgFvB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// createN8nConnector — Auto-discovery mode (the Growth Hack)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { N8nClient } from './N8nClient.js';
|
|
5
|
+
import { WorkflowDiscovery } from './WorkflowDiscovery.js';
|
|
6
|
+
import { synthesizeAll } from './ToolSynthesizer.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create an n8n connector that auto-discovers webhook workflows.
|
|
9
|
+
*
|
|
10
|
+
* If `pollInterval` is set, starts a background polling loop that
|
|
11
|
+
* re-discovers workflows and calls `onChange()` when the tool list changes.
|
|
12
|
+
* This enables zero-downtime hot-reload: the MCP server emits
|
|
13
|
+
* `notifications/tools/list_changed` and Claude refreshes instantly.
|
|
14
|
+
*/
|
|
15
|
+
export async function createN8nConnector(config) {
|
|
16
|
+
const clientConfig = {
|
|
17
|
+
url: config.url,
|
|
18
|
+
apiKey: config.apiKey,
|
|
19
|
+
...(config.timeout != null ? { timeout: config.timeout } : {}),
|
|
20
|
+
};
|
|
21
|
+
const client = new N8nClient(clientConfig);
|
|
22
|
+
const discoveryOpts = {
|
|
23
|
+
...(config.includeTags ? { includeTags: config.includeTags } : {}),
|
|
24
|
+
...(config.excludeTags ? { excludeTags: config.excludeTags } : {}),
|
|
25
|
+
};
|
|
26
|
+
const discovery = new WorkflowDiscovery(client, discoveryOpts);
|
|
27
|
+
let webhooks = await discovery.discover();
|
|
28
|
+
let synthesized = synthesizeAll(webhooks, client);
|
|
29
|
+
// ── Background Polling (Live State Sync) ──
|
|
30
|
+
let pollTimer = null;
|
|
31
|
+
/** Compute a fingerprint from tool names for change detection */
|
|
32
|
+
function fingerprint(tools) {
|
|
33
|
+
return tools.map(t => t.name).sort().join(',');
|
|
34
|
+
}
|
|
35
|
+
let lastFingerprint = fingerprint(synthesized);
|
|
36
|
+
/**
|
|
37
|
+
* Refresh and detect changes. Returns `true` if the tool list changed.
|
|
38
|
+
*/
|
|
39
|
+
async function refresh() {
|
|
40
|
+
webhooks = await discovery.discover();
|
|
41
|
+
const newSynth = synthesizeAll(webhooks, client);
|
|
42
|
+
const newFp = fingerprint(newSynth);
|
|
43
|
+
const changed = newFp !== lastFingerprint;
|
|
44
|
+
synthesized = newSynth;
|
|
45
|
+
lastFingerprint = newFp;
|
|
46
|
+
return changed;
|
|
47
|
+
}
|
|
48
|
+
// Start polling if interval is configured
|
|
49
|
+
if (config.pollInterval != null && config.pollInterval > 0) {
|
|
50
|
+
pollTimer = setInterval(async () => {
|
|
51
|
+
try {
|
|
52
|
+
const changed = await refresh();
|
|
53
|
+
if (changed && config.onChange) {
|
|
54
|
+
config.onChange();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Polling errors are silently swallowed — n8n might be
|
|
59
|
+
// temporarily unreachable. Next cycle will retry.
|
|
60
|
+
}
|
|
61
|
+
}, config.pollInterval);
|
|
62
|
+
// Ensure the timer doesn't prevent Node.js from exiting
|
|
63
|
+
if (typeof pollTimer === 'object' && 'unref' in pollTimer) {
|
|
64
|
+
pollTimer.unref();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
client,
|
|
69
|
+
get workflows() {
|
|
70
|
+
return webhooks;
|
|
71
|
+
},
|
|
72
|
+
tools() {
|
|
73
|
+
return synthesized;
|
|
74
|
+
},
|
|
75
|
+
refresh,
|
|
76
|
+
stop() {
|
|
77
|
+
if (pollTimer != null) {
|
|
78
|
+
clearInterval(pollTimer);
|
|
79
|
+
pollTimer = null;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=createN8nConnector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createN8nConnector.js","sourceRoot":"","sources":["../src/createN8nConnector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { N8nClient } from './N8nClient.js';
|
|
2
|
+
import type { N8nToolConfig } from './types.js';
|
|
3
|
+
import type { SynthesizedTool } from './ToolSynthesizer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Manually define an n8n workflow as an MCP Fusion tool.
|
|
6
|
+
*
|
|
7
|
+
* For when architects need surgical control: strict Zod params,
|
|
8
|
+
* custom annotations, specific middleware chains.
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const deploy = defineN8nTool('deploy_staging', client, {
|
|
12
|
+
* workflowId: 15,
|
|
13
|
+
* webhookPath: '/webhook/deploy',
|
|
14
|
+
* params: {
|
|
15
|
+
* branch: 'string',
|
|
16
|
+
* environment: { type: 'string', enum: ['staging', 'production'] },
|
|
17
|
+
* },
|
|
18
|
+
* annotations: { destructiveHint: true },
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const builder = defineTool(deploy.name, deploy.config);
|
|
22
|
+
* registry.register(builder);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function defineN8nTool<TContext = void>(name: string, client: N8nClient, config: N8nToolConfig<TContext>): SynthesizedTool;
|
|
26
|
+
//# sourceMappingURL=defineN8nTool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineN8nTool.d.ts","sourceRoot":"","sources":["../src/defineN8nTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,sBAAsB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,QAAQ,GAAG,IAAI,EACzC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAChC,eAAe,CAmEjB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// defineN8nTool — Manual/surgical mode (the Enterprise Weapon)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Manually define an n8n workflow as an MCP Fusion tool.
|
|
6
|
+
*
|
|
7
|
+
* For when architects need surgical control: strict Zod params,
|
|
8
|
+
* custom annotations, specific middleware chains.
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const deploy = defineN8nTool('deploy_staging', client, {
|
|
12
|
+
* workflowId: 15,
|
|
13
|
+
* webhookPath: '/webhook/deploy',
|
|
14
|
+
* params: {
|
|
15
|
+
* branch: 'string',
|
|
16
|
+
* environment: { type: 'string', enum: ['staging', 'production'] },
|
|
17
|
+
* },
|
|
18
|
+
* annotations: { destructiveHint: true },
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const builder = defineTool(deploy.name, deploy.config);
|
|
22
|
+
* registry.register(builder);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function defineN8nTool(name, client, config) {
|
|
26
|
+
const method = (config.method ?? 'POST').toUpperCase();
|
|
27
|
+
const isReadOnly = method === 'GET';
|
|
28
|
+
// Build params from user-provided definitions
|
|
29
|
+
const params = {};
|
|
30
|
+
if (config.params) {
|
|
31
|
+
for (const [key, def] of Object.entries(config.params)) {
|
|
32
|
+
if (typeof def === 'string') {
|
|
33
|
+
params[key] = def;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
params[key] = {
|
|
37
|
+
type: def.type,
|
|
38
|
+
...(def.enum ? { enum: def.enum } : {}),
|
|
39
|
+
...(def.description ? { description: def.description } : {}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Build handler
|
|
45
|
+
const handler = async (_ctx, args) => {
|
|
46
|
+
const response = await client.callWebhook(config.webhookPath, method, args);
|
|
47
|
+
if (response.status >= 400) {
|
|
48
|
+
return {
|
|
49
|
+
isError: true,
|
|
50
|
+
content: [{
|
|
51
|
+
type: 'text',
|
|
52
|
+
text: `n8n workflow error (HTTP ${response.status}): ${JSON.stringify(response.data)}`,
|
|
53
|
+
}],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
content: [{
|
|
58
|
+
type: 'text',
|
|
59
|
+
text: JSON.stringify(response.data, null, 2),
|
|
60
|
+
}],
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const description = config.description ??
|
|
64
|
+
`[n8n Workflow #${config.workflowId}] ${name}`;
|
|
65
|
+
return {
|
|
66
|
+
name,
|
|
67
|
+
config: {
|
|
68
|
+
description,
|
|
69
|
+
tags: config.tags ? [...config.tags] : [],
|
|
70
|
+
actions: {
|
|
71
|
+
execute: {
|
|
72
|
+
description: `Execute workflow #${config.workflowId}`,
|
|
73
|
+
params,
|
|
74
|
+
handler,
|
|
75
|
+
annotations: config.annotations ?? {
|
|
76
|
+
readOnlyHint: isReadOnly,
|
|
77
|
+
...(isReadOnly ? {} : { destructiveHint: false }),
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=defineN8nTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineN8nTool.js","sourceRoot":"","sources":["../src/defineN8nTool.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+DAA+D;AAC/D,+EAA+E;AAM/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,aAAa,CACzB,IAAY,EACZ,MAAiB,EACjB,MAA+B;IAE/B,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACvD,MAAM,UAAU,GAAG,MAAM,KAAK,KAAK,CAAC;IAEpC,8CAA8C;IAC9C,MAAM,MAAM,GAA8F,EAAE,CAAC;IAC7G,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,GAAG,CAAC,GAAG;oBACV,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC/D,CAAC;YACN,CAAC;QACL,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,KAAK,EAAE,IAAa,EAAE,IAA6B,EAAE,EAAE;QACnE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CACrC,MAAM,CAAC,WAAW,EAClB,MAAM,EACN,IAAI,CACP,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACzB,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,CAAC;wBACN,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,4BAA4B,QAAQ,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;qBACzF,CAAC;aACL,CAAC;QACN,CAAC;QAED,OAAO;YACH,OAAO,EAAE,CAAC;oBACN,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC/C,CAAC;SACL,CAAC;IACN,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW;QAClC,kBAAkB,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;IAEnD,OAAO;QACH,IAAI;QACJ,MAAM,EAAE;YACJ,WAAW;YACX,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;YACzC,OAAO,EAAE;gBACL,OAAO,EAAE;oBACL,WAAW,EAAE,qBAAqB,MAAM,CAAC,UAAU,EAAE;oBACrD,MAAM;oBACN,OAAO;oBACP,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI;wBAC/B,YAAY,EAAE,UAAU;wBACxB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;qBACpD;iBACJ;aACJ;SACJ;KACJ,CAAC;AACN,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { createN8nConnector } from './createN8nConnector.js';
|
|
2
|
+
export type { N8nConnector } from './createN8nConnector.js';
|
|
3
|
+
export { defineN8nTool } from './defineN8nTool.js';
|
|
4
|
+
export { N8nClient } from './N8nClient.js';
|
|
5
|
+
export type { N8nClientConfig } from './N8nClient.js';
|
|
6
|
+
export { WorkflowDiscovery } from './WorkflowDiscovery.js';
|
|
7
|
+
export type { DiscoveryOptions } from './WorkflowDiscovery.js';
|
|
8
|
+
export { inferSchema } from './SchemaInferrer.js';
|
|
9
|
+
export { synthesizeTool, synthesizeAll, toToolName } from './ToolSynthesizer.js';
|
|
10
|
+
export type { SynthesizedTool, SynthesizedAction } from './ToolSynthesizer.js';
|
|
11
|
+
export type { N8nWorkflow, N8nNode, N8nTag, N8nWebhookResponse, N8nConnectorConfig, N8nToolConfig, WebhookConfig, QueryParam, ParamDef, } from './types.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG/E,YAAY,EACR,WAAW,EACX,OAAO,EACP,MAAM,EACN,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,UAAU,EACV,QAAQ,GACX,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// @vinkius-core/mcp-fusion-n8n — Barrel Export
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// ── Primary API ──
|
|
5
|
+
export { createN8nConnector } from './createN8nConnector.js';
|
|
6
|
+
export { defineN8nTool } from './defineN8nTool.js';
|
|
7
|
+
// ── Client ──
|
|
8
|
+
export { N8nClient } from './N8nClient.js';
|
|
9
|
+
// ── Discovery ──
|
|
10
|
+
export { WorkflowDiscovery } from './WorkflowDiscovery.js';
|
|
11
|
+
// ── Schema Inference ──
|
|
12
|
+
export { inferSchema } from './SchemaInferrer.js';
|
|
13
|
+
// ── Tool Synthesis ──
|
|
14
|
+
export { synthesizeTool, synthesizeAll, toToolName } from './ToolSynthesizer.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+CAA+C;AAC/C,+EAA+E;AAE/E,oBAAoB;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,kBAAkB;AAClB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,yBAAyB;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** Workflow node from n8n API */
|
|
2
|
+
export interface N8nNode {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly parameters: Record<string, unknown>;
|
|
6
|
+
readonly position: readonly [number, number];
|
|
7
|
+
}
|
|
8
|
+
/** Workflow from n8n GET /api/v1/workflows */
|
|
9
|
+
export interface N8nWorkflow {
|
|
10
|
+
readonly id: number;
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly active: boolean;
|
|
13
|
+
readonly tags: readonly N8nTag[];
|
|
14
|
+
readonly nodes: readonly N8nNode[];
|
|
15
|
+
readonly createdAt: string;
|
|
16
|
+
readonly updatedAt: string;
|
|
17
|
+
/** User-facing notes/description (the "Hack Semântico" field) */
|
|
18
|
+
readonly meta?: {
|
|
19
|
+
readonly notes?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Tag from n8n API */
|
|
23
|
+
export interface N8nTag {
|
|
24
|
+
readonly id: number;
|
|
25
|
+
readonly name: string;
|
|
26
|
+
}
|
|
27
|
+
/** Webhook node configuration extracted from a workflow */
|
|
28
|
+
export interface WebhookConfig {
|
|
29
|
+
readonly workflowId: number;
|
|
30
|
+
readonly workflowName: string;
|
|
31
|
+
readonly path: string;
|
|
32
|
+
readonly method: string;
|
|
33
|
+
readonly description: string;
|
|
34
|
+
readonly tags: readonly string[];
|
|
35
|
+
readonly queryParams: readonly QueryParam[];
|
|
36
|
+
}
|
|
37
|
+
/** Query parameter extracted from webhook node */
|
|
38
|
+
export interface QueryParam {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly type: 'string' | 'number' | 'boolean';
|
|
41
|
+
readonly required: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** n8n webhook execution response */
|
|
44
|
+
export interface N8nWebhookResponse {
|
|
45
|
+
readonly status: number;
|
|
46
|
+
readonly data: unknown;
|
|
47
|
+
readonly executionId?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Configuration for the n8n connector */
|
|
50
|
+
export interface N8nConnectorConfig {
|
|
51
|
+
/** n8n instance base URL (e.g., http://localhost:5678) */
|
|
52
|
+
readonly url: string;
|
|
53
|
+
/** n8n REST API key */
|
|
54
|
+
readonly apiKey: string;
|
|
55
|
+
/** Only expose workflows with these tags */
|
|
56
|
+
readonly includeTags?: readonly string[];
|
|
57
|
+
/** Exclude workflows with these tags */
|
|
58
|
+
readonly excludeTags?: readonly string[];
|
|
59
|
+
/** Webhook call timeout in ms (default: 30000) */
|
|
60
|
+
readonly timeout?: number;
|
|
61
|
+
/** Polling interval in ms for live state sync (default: off). Set to enable auto-refresh. */
|
|
62
|
+
readonly pollInterval?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Called when the tool list changes after a poll cycle.
|
|
65
|
+
* Use this to emit `notifications/tools/list_changed` on your MCP server.
|
|
66
|
+
*/
|
|
67
|
+
readonly onChange?: () => void;
|
|
68
|
+
}
|
|
69
|
+
/** Configuration for manually defining an n8n tool */
|
|
70
|
+
export interface N8nToolConfig<TContext = void> {
|
|
71
|
+
/** n8n workflow ID */
|
|
72
|
+
readonly workflowId: number;
|
|
73
|
+
/** Webhook path (e.g., '/webhook/lead-enrichment') */
|
|
74
|
+
readonly webhookPath: string;
|
|
75
|
+
/** HTTP method (default: 'POST') */
|
|
76
|
+
readonly method?: string;
|
|
77
|
+
/** Tool description for the LLM */
|
|
78
|
+
readonly description?: string;
|
|
79
|
+
/** Parameter definitions (JSON-first, like defineTool) */
|
|
80
|
+
readonly params?: Record<string, ParamDef>;
|
|
81
|
+
/** MCP annotations */
|
|
82
|
+
readonly annotations?: {
|
|
83
|
+
readonly readOnlyHint?: boolean;
|
|
84
|
+
readonly destructiveHint?: boolean;
|
|
85
|
+
};
|
|
86
|
+
/** Tags for filtering */
|
|
87
|
+
readonly tags?: readonly string[];
|
|
88
|
+
}
|
|
89
|
+
/** Parameter definition (JSON-first) */
|
|
90
|
+
export type ParamDef = string | {
|
|
91
|
+
readonly type: string;
|
|
92
|
+
readonly enum?: readonly string[];
|
|
93
|
+
readonly description?: string;
|
|
94
|
+
readonly required?: boolean;
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// n8n API Types — Internal type definitions for the n8n REST API
|
|
3
|
+
// ============================================================================
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iEAAiE;AACjE,+EAA+E"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vinkius-core/mcp-fusion-n8n",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "n8n connector for MCP Fusion. Auto-discovers webhook workflows and produces ToolBuilders — so AI agents can call your automations natively.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"n8n",
|
|
22
|
+
"mcp-fusion",
|
|
23
|
+
"workflow",
|
|
24
|
+
"automation",
|
|
25
|
+
"ai",
|
|
26
|
+
"llm",
|
|
27
|
+
"connector"
|
|
28
|
+
],
|
|
29
|
+
"author": "Vinkius Labs",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/vinkius-labs/mcp-fusion.git",
|
|
33
|
+
"directory": "packages/n8n"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/vinkius-labs/mcp-fusion/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://mcp-fusion.vinkius.com/",
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@vinkius-core/mcp-fusion": "^2.0.0",
|
|
51
|
+
"zod": "^3.25.1 || ^4.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.3.0"
|
|
55
|
+
},
|
|
56
|
+
"license": "Apache-2.0"
|
|
57
|
+
}
|