@n8n-as-code/mcp 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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/services/mcp-server.d.ts +3 -0
- package/dist/services/mcp-server.d.ts.map +1 -0
- package/dist/services/mcp-server.js +86 -0
- package/dist/services/mcp-server.js.map +1 -0
- package/dist/services/mcp-service.d.ts +39 -0
- package/dist/services/mcp-service.d.ts.map +1 -0
- package/dist/services/mcp-service.js +142 -0
- package/dist/services/mcp-service.js.map +1 -0
- package/package.json +39 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startN8nAsCodeMcpServer } from './services/mcp-server.js';
|
|
3
|
+
const cwdArgIndex = process.argv.indexOf('--cwd');
|
|
4
|
+
const cwd = cwdArgIndex >= 0 ? process.argv[cwdArgIndex + 1] : process.env.N8N_AS_CODE_PROJECT_DIR;
|
|
5
|
+
await startN8nAsCodeMcpServer({ cwd });
|
|
6
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAClD,MAAM,GAAG,GAAG,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;AAEnG,MAAM,uBAAuB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/services/mcp-server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAMxF,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,0BAA+B,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GrG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { N8nAsCodeMcpService } from './mcp-service.js';
|
|
5
|
+
function asJsonText(data) {
|
|
6
|
+
return JSON.stringify(data, null, 2);
|
|
7
|
+
}
|
|
8
|
+
export async function startN8nAsCodeMcpServer(options = {}) {
|
|
9
|
+
const service = new N8nAsCodeMcpService(options);
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: 'n8n-as-code',
|
|
12
|
+
version: '1.0.0',
|
|
13
|
+
});
|
|
14
|
+
server.tool('search_n8n_knowledge', 'Search the local n8n-as-code knowledge base for nodes, documentation, and examples.', {
|
|
15
|
+
query: z.string().min(1).describe('Natural-language search query, for example "google sheets" or "AI agent".'),
|
|
16
|
+
category: z.string().optional().describe('Optional documentation category filter.'),
|
|
17
|
+
type: z.enum(['node', 'documentation']).optional().describe('Optional result type filter.'),
|
|
18
|
+
limit: z.number().int().min(1).max(25).optional().describe('Maximum number of results to return.'),
|
|
19
|
+
}, async ({ query, category, type, limit }) => ({
|
|
20
|
+
content: [{ type: 'text', text: asJsonText(await service.searchKnowledge(query, { category, type, limit })) }],
|
|
21
|
+
}));
|
|
22
|
+
server.tool('get_n8n_node_info', 'Get the full offline schema and metadata for a specific n8n node.', {
|
|
23
|
+
name: z.string().min(1).describe('Exact or close node name, for example "googleSheets" or "n8n-nodes-base.httpRequest".'),
|
|
24
|
+
}, async ({ name }) => {
|
|
25
|
+
try {
|
|
26
|
+
return {
|
|
27
|
+
content: [{ type: 'text', text: asJsonText(await service.getNodeInfo(name)) }],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return {
|
|
32
|
+
isError: true,
|
|
33
|
+
content: [{ type: 'text', text: error.message }],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
server.tool('search_n8n_workflow_examples', 'Search the bundled n8n community workflow index for reusable example workflows.', {
|
|
38
|
+
query: z.string().min(1).describe('Search query, for example "slack notification" or "invoice processing".'),
|
|
39
|
+
limit: z.number().int().min(1).max(25).optional().describe('Maximum number of workflow examples to return.'),
|
|
40
|
+
}, async ({ query, limit }) => ({
|
|
41
|
+
content: [{ type: 'text', text: asJsonText(await service.searchExamples(query, limit)) }],
|
|
42
|
+
}));
|
|
43
|
+
server.tool('get_n8n_workflow_example', 'Get metadata and the raw download URL for a specific community workflow example.', {
|
|
44
|
+
id: z.string().min(1).describe('Workflow example ID from search_n8n_workflow_examples.'),
|
|
45
|
+
}, async ({ id }) => {
|
|
46
|
+
try {
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: 'text', text: asJsonText(await service.getExampleInfo(id)) }],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
isError: true,
|
|
54
|
+
content: [{ type: 'text', text: error.message }],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
server.tool('validate_n8n_workflow', 'Validate an n8n workflow from JSON or TypeScript content against the bundled schema.', {
|
|
59
|
+
workflowContent: z.string().min(1).describe('Workflow source as JSON or .workflow.ts text.'),
|
|
60
|
+
format: z.enum(['auto', 'json', 'typescript']).optional().describe('Optional workflow format override.'),
|
|
61
|
+
}, async ({ workflowContent, format }) => {
|
|
62
|
+
try {
|
|
63
|
+
const result = await service.validateWorkflow({ workflowContent, format });
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: 'text', text: asJsonText(result) }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
isError: true,
|
|
71
|
+
content: [{ type: 'text', text: error.message }],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
server.tool('search_n8n_docs', 'Search bundled n8n documentation pages and return matching excerpts.', {
|
|
76
|
+
query: z.string().min(1).describe('Documentation search query.'),
|
|
77
|
+
category: z.string().optional().describe('Optional documentation category filter.'),
|
|
78
|
+
type: z.enum(['node', 'documentation']).optional().describe('Optional result type filter. Defaults to documentation.'),
|
|
79
|
+
limit: z.number().int().min(1).max(10).optional().describe('Maximum number of pages to return.'),
|
|
80
|
+
}, async ({ query, category, type, limit }) => ({
|
|
81
|
+
content: [{ type: 'text', text: asJsonText(await service.searchDocs(query, { category, type, limit })) }],
|
|
82
|
+
}));
|
|
83
|
+
const transport = new StdioServerTransport();
|
|
84
|
+
await server.connect(transport);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/services/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface N8nAsCodeMcpServiceOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
}
|
|
4
|
+
export interface ValidateWorkflowOptions {
|
|
5
|
+
workflowContent: string;
|
|
6
|
+
format?: 'auto' | 'json' | 'typescript';
|
|
7
|
+
}
|
|
8
|
+
export interface CliExecutionResult {
|
|
9
|
+
command: string[];
|
|
10
|
+
cwd: string;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
success: boolean;
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
parsedJson?: unknown;
|
|
16
|
+
}
|
|
17
|
+
export declare class N8nAsCodeMcpService {
|
|
18
|
+
readonly cwd: string;
|
|
19
|
+
constructor(options?: N8nAsCodeMcpServiceOptions);
|
|
20
|
+
private getCliEntryPath;
|
|
21
|
+
private runCliCommand;
|
|
22
|
+
private runCliJsonCommand;
|
|
23
|
+
searchKnowledge(query: string, options?: {
|
|
24
|
+
category?: string;
|
|
25
|
+
type?: 'node' | 'documentation';
|
|
26
|
+
limit?: number;
|
|
27
|
+
}): Promise<any>;
|
|
28
|
+
getNodeInfo(name: string): Promise<any>;
|
|
29
|
+
searchDocs(query: string, options?: {
|
|
30
|
+
category?: string;
|
|
31
|
+
type?: 'node' | 'documentation';
|
|
32
|
+
limit?: number;
|
|
33
|
+
}): Promise<any>;
|
|
34
|
+
searchExamples(query: string, limit?: number): Promise<any>;
|
|
35
|
+
getExampleInfo(id: string): Promise<any>;
|
|
36
|
+
validateWorkflow({ workflowContent, format }: ValidateWorkflowOptions): Promise<any>;
|
|
37
|
+
readWorkflowFile(path: string): string;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=mcp-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-service.d.ts","sourceRoot":"","sources":["../../src/services/mcp-service.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,0BAA0B;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAiBD,qBAAa,mBAAmB;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAET,OAAO,GAAE,0BAA+B;IAIpD,OAAO,CAAC,eAAe;YAMT,aAAa;YAqDb,iBAAiB;IAmB/B,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;IAQnH,WAAW,CAAC,IAAI,EAAE,MAAM;IAIlB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE;QACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;QAChC,KAAK,CAAC,EAAE,MAAM,CAAC;KACb;IAUN,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW;IAIhD,cAAc,CAAC,EAAE,EAAE,MAAM;IAInB,gBAAgB,CAAC,EAAE,eAAe,EAAE,MAAe,EAAE,EAAE,uBAAuB;IAsBpF,gBAAgB,CAAC,IAAI,EAAE,MAAM;CAGhC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { createRequire } from 'module';
|
|
6
|
+
function detectWorkflowFormat(workflowContent, format = 'auto') {
|
|
7
|
+
if (format === 'typescript') {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
if (format === 'json') {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const trimmed = workflowContent.trim();
|
|
14
|
+
return trimmed.startsWith('import ')
|
|
15
|
+
|| trimmed.startsWith('@workflow')
|
|
16
|
+
|| trimmed.includes('export class');
|
|
17
|
+
}
|
|
18
|
+
export class N8nAsCodeMcpService {
|
|
19
|
+
cwd;
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.cwd = options.cwd || process.cwd();
|
|
22
|
+
}
|
|
23
|
+
getCliEntryPath() {
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
const cliPkg = require.resolve('n8nac/package.json');
|
|
26
|
+
return join(dirname(cliPkg), 'dist', 'index.js');
|
|
27
|
+
}
|
|
28
|
+
async runCliCommand(args, parseJson = false) {
|
|
29
|
+
const cliEntryPath = this.getCliEntryPath();
|
|
30
|
+
return new Promise((resolvePromise, reject) => {
|
|
31
|
+
const child = spawn(process.execPath, [cliEntryPath, ...args], {
|
|
32
|
+
cwd: this.cwd,
|
|
33
|
+
env: {
|
|
34
|
+
...process.env,
|
|
35
|
+
FORCE_COLOR: '0',
|
|
36
|
+
NO_COLOR: '1',
|
|
37
|
+
},
|
|
38
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
39
|
+
});
|
|
40
|
+
let stdout = '';
|
|
41
|
+
let stderr = '';
|
|
42
|
+
child.stdout.on('data', (chunk) => {
|
|
43
|
+
stdout += chunk.toString();
|
|
44
|
+
});
|
|
45
|
+
child.stderr.on('data', (chunk) => {
|
|
46
|
+
stderr += chunk.toString();
|
|
47
|
+
});
|
|
48
|
+
child.on('error', reject);
|
|
49
|
+
child.on('close', (exitCode) => {
|
|
50
|
+
const trimmedStdout = stdout.trim();
|
|
51
|
+
const result = {
|
|
52
|
+
command: [process.execPath, cliEntryPath, ...args],
|
|
53
|
+
cwd: this.cwd,
|
|
54
|
+
exitCode: exitCode ?? 1,
|
|
55
|
+
success: exitCode === 0,
|
|
56
|
+
stdout: trimmedStdout,
|
|
57
|
+
stderr: stderr.trim(),
|
|
58
|
+
};
|
|
59
|
+
if (parseJson && trimmedStdout) {
|
|
60
|
+
try {
|
|
61
|
+
result.parsedJson = JSON.parse(trimmedStdout);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
result.parsedJson = {
|
|
65
|
+
parseError: error.message,
|
|
66
|
+
raw: trimmedStdout,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
resolvePromise(result);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async runCliJsonCommand(args) {
|
|
75
|
+
const result = await this.runCliCommand(args, true);
|
|
76
|
+
const parsed = result.parsedJson;
|
|
77
|
+
const hasParseError = parsed !== null &&
|
|
78
|
+
typeof parsed === 'object' &&
|
|
79
|
+
'parseError' in parsed;
|
|
80
|
+
if (typeof parsed !== 'undefined' && !hasParseError) {
|
|
81
|
+
return parsed;
|
|
82
|
+
}
|
|
83
|
+
if (!result.success) {
|
|
84
|
+
throw new Error(result.stderr || result.stdout || `CLI command failed: ${args.join(' ')}`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`CLI command did not return valid JSON: ${args.join(' ')}`);
|
|
87
|
+
}
|
|
88
|
+
searchKnowledge(query, options = {}) {
|
|
89
|
+
const args = ['skills', 'search', query, '--json'];
|
|
90
|
+
if (options.category)
|
|
91
|
+
args.push('--category', options.category);
|
|
92
|
+
if (options.type)
|
|
93
|
+
args.push('--type', options.type);
|
|
94
|
+
if (options.limit)
|
|
95
|
+
args.push('--limit', String(options.limit));
|
|
96
|
+
return this.runCliJsonCommand(args);
|
|
97
|
+
}
|
|
98
|
+
getNodeInfo(name) {
|
|
99
|
+
return this.runCliJsonCommand(['skills', 'node-info', name, '--json']);
|
|
100
|
+
}
|
|
101
|
+
async searchDocs(query, options = {}) {
|
|
102
|
+
const args = ['skills', 'search', query, '--json'];
|
|
103
|
+
if (options.category)
|
|
104
|
+
args.push('--category', options.category);
|
|
105
|
+
args.push('--type', options.type ?? 'documentation');
|
|
106
|
+
if (options.limit)
|
|
107
|
+
args.push('--limit', String(options.limit));
|
|
108
|
+
const result = await this.runCliJsonCommand(args);
|
|
109
|
+
return Array.isArray(result?.results) ? result.results : result;
|
|
110
|
+
}
|
|
111
|
+
searchExamples(query, limit = 10) {
|
|
112
|
+
return this.runCliJsonCommand(['skills', 'examples', 'search', query, '--json', '--limit', String(limit)]);
|
|
113
|
+
}
|
|
114
|
+
getExampleInfo(id) {
|
|
115
|
+
return this.runCliJsonCommand(['skills', 'examples', 'info', id, '--json']);
|
|
116
|
+
}
|
|
117
|
+
async validateWorkflow({ workflowContent, format = 'auto' }) {
|
|
118
|
+
const isTypeScript = detectWorkflowFormat(workflowContent, format);
|
|
119
|
+
const tempDir = mkdtempSync(join(tmpdir(), 'n8nac-mcp-validate-'));
|
|
120
|
+
const extension = isTypeScript ? '.workflow.ts' : '.json';
|
|
121
|
+
const tempFile = join(tempDir, `workflow${extension}`);
|
|
122
|
+
try {
|
|
123
|
+
if (!isTypeScript) {
|
|
124
|
+
try {
|
|
125
|
+
JSON.parse(workflowContent);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw new Error(`Invalid JSON workflow content: ${error.message}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
writeFileSync(tempFile, workflowContent, 'utf8');
|
|
132
|
+
return await this.runCliJsonCommand(['skills', 'validate', tempFile, '--json']);
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
readWorkflowFile(path) {
|
|
139
|
+
return readFileSync(path, 'utf8');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=mcp-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-service.js","sourceRoot":"","sources":["../../src/services/mcp-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@n8n-as-code/mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Dedicated MCP server for n8n-as-code",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"n8nac-mcp": "./dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc -b && chmod +x dist/cli.js",
|
|
14
|
+
"test": "node --experimental-vm-modules ../../node_modules/.bin/jest",
|
|
15
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
19
|
+
"zod": "^3.22.4"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/jest": "^29.5.11",
|
|
23
|
+
"@types/node": "^20.10.6",
|
|
24
|
+
"jest": "^29.7.0",
|
|
25
|
+
"ts-jest": "^29.1.1",
|
|
26
|
+
"typescript": "^5.3.3"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist/"
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/EtienneLescot/n8n-as-code",
|
|
34
|
+
"directory": "packages/mcp"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|