@emcy/openapi-to-mcp 0.2.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/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/__tests__/generator.test.d.ts +5 -0
- package/dist/__tests__/generator.test.d.ts.map +1 -0
- package/dist/__tests__/generator.test.js +236 -0
- package/dist/__tests__/generator.test.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +5 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.js +184 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/__tests__/mapper.test.d.ts +5 -0
- package/dist/__tests__/mapper.test.d.ts.map +1 -0
- package/dist/__tests__/mapper.test.js +250 -0
- package/dist/__tests__/mapper.test.js.map +1 -0
- package/dist/__tests__/parser.test.d.ts +5 -0
- package/dist/__tests__/parser.test.d.ts.map +1 -0
- package/dist/__tests__/parser.test.js +260 -0
- package/dist/__tests__/parser.test.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +235 -0
- package/dist/cli.js.map +1 -0
- package/dist/generator.d.ts +9 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +595 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mapper.d.ts +17 -0
- package/dist/mapper.d.ts.map +1 -0
- package/dist/mapper.js +79 -0
- package/dist/mapper.js.map +1 -0
- package/dist/parser.d.ts +31 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +183 -0
- package/dist/parser.js.map +1 -0
- package/dist/types.d.ts +97 -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 +72 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser tests - ensures OpenAPI specs are correctly parsed into our format
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { parseOpenAPI, validateOpenAPI, generateOperationId } from '../parser.js';
|
|
6
|
+
describe('generateOperationId', () => {
|
|
7
|
+
it('should generate operationId from simple path', () => {
|
|
8
|
+
expect(generateOperationId('get', '/users')).toBe('GetUsers');
|
|
9
|
+
expect(generateOperationId('post', '/orders')).toBe('PostOrders');
|
|
10
|
+
expect(generateOperationId('delete', '/products')).toBe('DeleteProducts');
|
|
11
|
+
});
|
|
12
|
+
it('should handle path parameters with "By" prefix', () => {
|
|
13
|
+
expect(generateOperationId('get', '/users/{id}')).toBe('GetUsersById');
|
|
14
|
+
expect(generateOperationId('get', '/orders/{orderId}')).toBe('GetOrdersByOrderId');
|
|
15
|
+
expect(generateOperationId('delete', '/products/{productId}')).toBe('DeleteProductsByProductId');
|
|
16
|
+
});
|
|
17
|
+
it('should handle multiple path segments', () => {
|
|
18
|
+
expect(generateOperationId('get', '/users/{userId}/orders')).toBe('GetUsersByUserIdOrders');
|
|
19
|
+
expect(generateOperationId('post', '/shops/{shopId}/products/{productId}')).toBe('PostShopsByShopIdProductsByProductId');
|
|
20
|
+
});
|
|
21
|
+
it('should handle nested paths with parameters', () => {
|
|
22
|
+
expect(generateOperationId('patch', '/orders/{id}/status')).toBe('PatchOrdersByIdStatus');
|
|
23
|
+
expect(generateOperationId('get', '/api/v1/users')).toBe('GetApiV1Users');
|
|
24
|
+
});
|
|
25
|
+
it('should handle root path', () => {
|
|
26
|
+
expect(generateOperationId('get', '/')).toBe('Get');
|
|
27
|
+
});
|
|
28
|
+
it('should capitalize method name', () => {
|
|
29
|
+
expect(generateOperationId('GET', '/users')).toBe('GetUsers');
|
|
30
|
+
expect(generateOperationId('POST', '/orders')).toBe('PostOrders');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('parseOpenAPI', () => {
|
|
34
|
+
it('should parse a minimal OpenAPI spec', async () => {
|
|
35
|
+
const spec = {
|
|
36
|
+
openapi: '3.0.0',
|
|
37
|
+
info: {
|
|
38
|
+
title: 'Test API',
|
|
39
|
+
version: '1.0.0',
|
|
40
|
+
},
|
|
41
|
+
paths: {},
|
|
42
|
+
};
|
|
43
|
+
const result = await parseOpenAPI(spec);
|
|
44
|
+
expect(result.title).toBe('Test API');
|
|
45
|
+
expect(result.version).toBe('1.0.0');
|
|
46
|
+
expect(result.endpoints).toEqual([]);
|
|
47
|
+
});
|
|
48
|
+
it('should parse endpoints from paths', async () => {
|
|
49
|
+
const spec = {
|
|
50
|
+
openapi: '3.0.0',
|
|
51
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
52
|
+
paths: {
|
|
53
|
+
'/users': {
|
|
54
|
+
get: {
|
|
55
|
+
summary: 'Get all users',
|
|
56
|
+
operationId: 'getUsers',
|
|
57
|
+
},
|
|
58
|
+
post: {
|
|
59
|
+
summary: 'Create user',
|
|
60
|
+
operationId: 'createUser',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const result = await parseOpenAPI(spec);
|
|
66
|
+
expect(result.endpoints).toHaveLength(2);
|
|
67
|
+
const getUsers = result.endpoints.find(e => e.operationId === 'getUsers');
|
|
68
|
+
expect(getUsers).toBeDefined();
|
|
69
|
+
expect(getUsers?.method).toBe('GET');
|
|
70
|
+
expect(getUsers?.path).toBe('/users');
|
|
71
|
+
expect(getUsers?.summary).toBe('Get all users');
|
|
72
|
+
const createUser = result.endpoints.find(e => e.operationId === 'createUser');
|
|
73
|
+
expect(createUser).toBeDefined();
|
|
74
|
+
expect(createUser?.method).toBe('POST');
|
|
75
|
+
});
|
|
76
|
+
it('should generate operationId when not provided', async () => {
|
|
77
|
+
const spec = {
|
|
78
|
+
openapi: '3.0.0',
|
|
79
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
80
|
+
paths: {
|
|
81
|
+
'/products/{id}': {
|
|
82
|
+
get: {
|
|
83
|
+
summary: 'Get product',
|
|
84
|
+
},
|
|
85
|
+
delete: {},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
const result = await parseOpenAPI(spec);
|
|
90
|
+
expect(result.endpoints).toHaveLength(2);
|
|
91
|
+
const getProduct = result.endpoints.find(e => e.method === 'GET');
|
|
92
|
+
expect(getProduct?.operationId).toBe('GetProductsById');
|
|
93
|
+
const deleteProduct = result.endpoints.find(e => e.method === 'DELETE');
|
|
94
|
+
expect(deleteProduct?.operationId).toBe('DeleteProductsById');
|
|
95
|
+
});
|
|
96
|
+
it('should parse path parameters', async () => {
|
|
97
|
+
const spec = {
|
|
98
|
+
openapi: '3.0.0',
|
|
99
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
100
|
+
paths: {
|
|
101
|
+
'/users/{userId}': {
|
|
102
|
+
get: {
|
|
103
|
+
parameters: [
|
|
104
|
+
{
|
|
105
|
+
name: 'userId',
|
|
106
|
+
in: 'path',
|
|
107
|
+
required: true,
|
|
108
|
+
schema: { type: 'integer' },
|
|
109
|
+
description: 'User ID',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
const result = await parseOpenAPI(spec);
|
|
117
|
+
expect(result.endpoints[0].parameters).toHaveLength(1);
|
|
118
|
+
expect(result.endpoints[0].parameters[0]).toEqual({
|
|
119
|
+
name: 'userId',
|
|
120
|
+
in: 'path',
|
|
121
|
+
required: true,
|
|
122
|
+
schema: { type: 'integer' },
|
|
123
|
+
description: 'User ID',
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
it('should parse query parameters', async () => {
|
|
127
|
+
const spec = {
|
|
128
|
+
openapi: '3.0.0',
|
|
129
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
130
|
+
paths: {
|
|
131
|
+
'/users': {
|
|
132
|
+
get: {
|
|
133
|
+
parameters: [
|
|
134
|
+
{
|
|
135
|
+
name: 'limit',
|
|
136
|
+
in: 'query',
|
|
137
|
+
required: false,
|
|
138
|
+
schema: { type: 'integer', default: 10 },
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'offset',
|
|
142
|
+
in: 'query',
|
|
143
|
+
schema: { type: 'integer' },
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const result = await parseOpenAPI(spec);
|
|
151
|
+
expect(result.endpoints[0].parameters).toHaveLength(2);
|
|
152
|
+
expect(result.endpoints[0].parameters[0].name).toBe('limit');
|
|
153
|
+
expect(result.endpoints[0].parameters[0].required).toBe(false);
|
|
154
|
+
expect(result.endpoints[0].parameters[1].name).toBe('offset');
|
|
155
|
+
});
|
|
156
|
+
it('should parse request body', async () => {
|
|
157
|
+
const spec = {
|
|
158
|
+
openapi: '3.0.0',
|
|
159
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
160
|
+
paths: {
|
|
161
|
+
'/users': {
|
|
162
|
+
post: {
|
|
163
|
+
requestBody: {
|
|
164
|
+
required: true,
|
|
165
|
+
content: {
|
|
166
|
+
'application/json': {
|
|
167
|
+
schema: {
|
|
168
|
+
type: 'object',
|
|
169
|
+
properties: {
|
|
170
|
+
name: { type: 'string' },
|
|
171
|
+
email: { type: 'string' },
|
|
172
|
+
},
|
|
173
|
+
required: ['name', 'email'],
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
const result = await parseOpenAPI(spec);
|
|
183
|
+
expect(result.endpoints[0].requestBody).toBeDefined();
|
|
184
|
+
expect(result.endpoints[0].requestBody?.required).toBe(true);
|
|
185
|
+
expect(result.endpoints[0].requestBody?.contentType).toBe('application/json');
|
|
186
|
+
expect(result.endpoints[0].requestBody?.schema.type).toBe('object');
|
|
187
|
+
});
|
|
188
|
+
it('should parse security schemes', async () => {
|
|
189
|
+
const spec = {
|
|
190
|
+
openapi: '3.0.0',
|
|
191
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
192
|
+
paths: {
|
|
193
|
+
'/secure': {
|
|
194
|
+
get: {
|
|
195
|
+
security: [{ apiKey: [] }],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
components: {
|
|
200
|
+
securitySchemes: {
|
|
201
|
+
apiKey: {
|
|
202
|
+
type: 'apiKey',
|
|
203
|
+
name: 'X-API-Key',
|
|
204
|
+
in: 'header',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const result = await parseOpenAPI(spec);
|
|
210
|
+
expect(result.endpoints[0].securitySchemes).toEqual(['apiKey']);
|
|
211
|
+
expect(result.securitySchemes.apiKey).toEqual({
|
|
212
|
+
type: 'apiKey',
|
|
213
|
+
name: 'X-API-Key',
|
|
214
|
+
in: 'header',
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
it('should extract base URL from servers', async () => {
|
|
218
|
+
const spec = {
|
|
219
|
+
openapi: '3.0.0',
|
|
220
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
221
|
+
servers: [{ url: 'https://api.example.com/v1' }],
|
|
222
|
+
paths: {},
|
|
223
|
+
};
|
|
224
|
+
const result = await parseOpenAPI(spec);
|
|
225
|
+
expect(result.baseUrl).toBe('https://api.example.com/v1');
|
|
226
|
+
});
|
|
227
|
+
it('should handle missing servers', async () => {
|
|
228
|
+
const spec = {
|
|
229
|
+
openapi: '3.0.0',
|
|
230
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
231
|
+
paths: {},
|
|
232
|
+
};
|
|
233
|
+
const result = await parseOpenAPI(spec);
|
|
234
|
+
expect(result.baseUrl).toBe('');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
describe('validateOpenAPI', () => {
|
|
238
|
+
it('should validate a correct spec', async () => {
|
|
239
|
+
const spec = {
|
|
240
|
+
openapi: '3.0.0',
|
|
241
|
+
info: { title: 'Test API', version: '1.0.0' },
|
|
242
|
+
paths: {},
|
|
243
|
+
};
|
|
244
|
+
const result = await validateOpenAPI(spec);
|
|
245
|
+
expect(result.valid).toBe(true);
|
|
246
|
+
expect(result.errors).toBeUndefined();
|
|
247
|
+
});
|
|
248
|
+
it('should reject an invalid spec', async () => {
|
|
249
|
+
const spec = {
|
|
250
|
+
// Missing required 'openapi' field
|
|
251
|
+
info: { title: 'Test API' },
|
|
252
|
+
paths: {},
|
|
253
|
+
};
|
|
254
|
+
const result = await validateOpenAPI(spec);
|
|
255
|
+
expect(result.valid).toBe(false);
|
|
256
|
+
expect(result.errors).toBeDefined();
|
|
257
|
+
expect(result.errors?.length).toBeGreaterThan(0);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
//# sourceMappingURL=parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../../src/__tests__/parser.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @emcy/openapi-to-mcp CLI
|
|
4
|
+
*
|
|
5
|
+
* Convert OpenAPI specifications to MCP servers with optional Emcy telemetry.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx @emcy/openapi-to-mcp generate --url https://api.example.com/openapi.json
|
|
9
|
+
* npx @emcy/openapi-to-mcp generate --url ./openapi.yaml --name my-api --emcy
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @emcy/openapi-to-mcp CLI
|
|
4
|
+
*
|
|
5
|
+
* Convert OpenAPI specifications to MCP servers with optional Emcy telemetry.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx @emcy/openapi-to-mcp generate --url https://api.example.com/openapi.json
|
|
9
|
+
* npx @emcy/openapi-to-mcp generate --url ./openapi.yaml --name my-api --emcy
|
|
10
|
+
*/
|
|
11
|
+
import { parseArgs } from 'node:util';
|
|
12
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { existsSync } from 'node:fs';
|
|
15
|
+
import { parseOpenAPI, validateOpenAPI } from './parser.js';
|
|
16
|
+
import { mapToMcpTools } from './mapper.js';
|
|
17
|
+
import { generateMcpServer } from './generator.js';
|
|
18
|
+
const VERSION = '0.1.0';
|
|
19
|
+
const HELP = `
|
|
20
|
+
@emcy/openapi-to-mcp - Convert OpenAPI specs to MCP servers
|
|
21
|
+
|
|
22
|
+
USAGE:
|
|
23
|
+
npx @emcy/openapi-to-mcp <command> [options]
|
|
24
|
+
|
|
25
|
+
COMMANDS:
|
|
26
|
+
generate Generate an MCP server from an OpenAPI specification
|
|
27
|
+
validate Validate an OpenAPI specification
|
|
28
|
+
help Show this help message
|
|
29
|
+
|
|
30
|
+
GENERATE OPTIONS:
|
|
31
|
+
--url, -u URL or file path to OpenAPI specification (required)
|
|
32
|
+
--name, -n Name for the generated MCP server (default: from spec title)
|
|
33
|
+
--output, -o Output directory (default: ./<name>-mcp-server)
|
|
34
|
+
--emcy, -e Enable Emcy telemetry integration
|
|
35
|
+
--base-url, -b Override base URL for API calls
|
|
36
|
+
--version Version string for the server (default: from spec)
|
|
37
|
+
--force, -f Overwrite existing output directory
|
|
38
|
+
--local-sdk Path to local @emcy/sdk for development (uses file: reference)
|
|
39
|
+
|
|
40
|
+
EXAMPLES:
|
|
41
|
+
# Generate from a URL
|
|
42
|
+
npx @emcy/openapi-to-mcp generate --url https://petstore.swagger.io/v2/swagger.json
|
|
43
|
+
|
|
44
|
+
# Generate from a local file with Emcy telemetry
|
|
45
|
+
npx @emcy/openapi-to-mcp generate --url ./openapi.yaml --name my-api --emcy
|
|
46
|
+
|
|
47
|
+
# Generate with custom output directory
|
|
48
|
+
npx @emcy/openapi-to-mcp generate --url ./api.json -o ./my-mcp-server
|
|
49
|
+
|
|
50
|
+
# Validate an OpenAPI spec
|
|
51
|
+
npx @emcy/openapi-to-mcp validate --url https://api.example.com/openapi.json
|
|
52
|
+
`;
|
|
53
|
+
async function main() {
|
|
54
|
+
const args = process.argv.slice(2);
|
|
55
|
+
const command = args[0];
|
|
56
|
+
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
57
|
+
console.log(HELP);
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
if (command === '--version' || command === '-v') {
|
|
61
|
+
console.log(`@emcy/openapi-to-mcp v${VERSION}`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
if (command === 'validate') {
|
|
65
|
+
await runValidate(args.slice(1));
|
|
66
|
+
}
|
|
67
|
+
else if (command === 'generate') {
|
|
68
|
+
await runGenerate(args.slice(1));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.error(`Unknown command: ${command}`);
|
|
72
|
+
console.log('Run with --help for usage information.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function runValidate(args) {
|
|
77
|
+
const { values } = parseArgs({
|
|
78
|
+
args,
|
|
79
|
+
options: {
|
|
80
|
+
url: { type: 'string', short: 'u' },
|
|
81
|
+
},
|
|
82
|
+
allowPositionals: false,
|
|
83
|
+
});
|
|
84
|
+
if (!values.url) {
|
|
85
|
+
console.error('Error: --url is required');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
console.log(`Validating: ${values.url}`);
|
|
89
|
+
try {
|
|
90
|
+
const input = await loadSpec(values.url);
|
|
91
|
+
const result = await validateOpenAPI(input);
|
|
92
|
+
if (result.valid) {
|
|
93
|
+
console.log('✓ OpenAPI specification is valid');
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
console.error('✗ OpenAPI specification is invalid:');
|
|
98
|
+
for (const error of result.errors || []) {
|
|
99
|
+
console.error(` - ${error}`);
|
|
100
|
+
}
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error('Error validating spec:', error instanceof Error ? error.message : error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function runGenerate(args) {
|
|
110
|
+
const { values } = parseArgs({
|
|
111
|
+
args,
|
|
112
|
+
options: {
|
|
113
|
+
url: { type: 'string', short: 'u' },
|
|
114
|
+
name: { type: 'string', short: 'n' },
|
|
115
|
+
output: { type: 'string', short: 'o' },
|
|
116
|
+
emcy: { type: 'boolean', short: 'e', default: false },
|
|
117
|
+
'base-url': { type: 'string', short: 'b' },
|
|
118
|
+
version: { type: 'string' },
|
|
119
|
+
force: { type: 'boolean', short: 'f', default: false },
|
|
120
|
+
'local-sdk': { type: 'string' }, // Path to local @emcy/sdk for dev
|
|
121
|
+
},
|
|
122
|
+
allowPositionals: false,
|
|
123
|
+
});
|
|
124
|
+
if (!values.url) {
|
|
125
|
+
console.error('Error: --url is required');
|
|
126
|
+
console.log('Usage: npx @emcy/openapi-to-mcp generate --url <openapi-url-or-path>');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
console.log(`\n🔧 @emcy/openapi-to-mcp Generator\n`);
|
|
130
|
+
console.log(`Loading OpenAPI spec from: ${values.url}`);
|
|
131
|
+
try {
|
|
132
|
+
// Load and parse the spec
|
|
133
|
+
const input = await loadSpec(values.url);
|
|
134
|
+
const parsed = await parseOpenAPI(input);
|
|
135
|
+
console.log(` Title: ${parsed.title}`);
|
|
136
|
+
console.log(` Version: ${parsed.version}`);
|
|
137
|
+
console.log(` Endpoints: ${parsed.endpoints.length}`);
|
|
138
|
+
console.log(` Base URL: ${parsed.baseUrl || '(not specified)'}`);
|
|
139
|
+
// Map to MCP tools
|
|
140
|
+
const tools = mapToMcpTools(parsed.endpoints);
|
|
141
|
+
console.log(` Tools: ${tools.length}`);
|
|
142
|
+
// Determine output settings
|
|
143
|
+
const serverName = values.name || slugify(parsed.title);
|
|
144
|
+
const outputDir = values.output || `./${serverName}-mcp-server`;
|
|
145
|
+
const resolvedOutput = resolve(outputDir);
|
|
146
|
+
// Check if output exists
|
|
147
|
+
if (existsSync(resolvedOutput) && !values.force) {
|
|
148
|
+
console.error(`\nError: Output directory already exists: ${resolvedOutput}`);
|
|
149
|
+
console.error('Use --force to overwrite.');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
console.log(`\nGenerating MCP server: ${serverName}`);
|
|
153
|
+
console.log(` Output: ${resolvedOutput}`);
|
|
154
|
+
console.log(` Emcy Telemetry: ${values.emcy ? 'enabled' : 'disabled'}`);
|
|
155
|
+
if (values['local-sdk']) {
|
|
156
|
+
console.log(` Local SDK: ${values['local-sdk']}`);
|
|
157
|
+
}
|
|
158
|
+
// Generate the server
|
|
159
|
+
const files = generateMcpServer(tools, {
|
|
160
|
+
name: serverName,
|
|
161
|
+
version: values.version || parsed.version || '1.0.0',
|
|
162
|
+
baseUrl: values['base-url'] || parsed.baseUrl || 'http://localhost:3000',
|
|
163
|
+
emcyEnabled: values.emcy || false,
|
|
164
|
+
localSdkPath: values['local-sdk'],
|
|
165
|
+
}, parsed.securitySchemes);
|
|
166
|
+
// Write files
|
|
167
|
+
await mkdir(resolvedOutput, { recursive: true });
|
|
168
|
+
await mkdir(join(resolvedOutput, 'src'), { recursive: true });
|
|
169
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
170
|
+
const fullPath = join(resolvedOutput, filePath);
|
|
171
|
+
const dir = join(resolvedOutput, filePath.split('/').slice(0, -1).join('/'));
|
|
172
|
+
if (dir !== resolvedOutput) {
|
|
173
|
+
await mkdir(dir, { recursive: true });
|
|
174
|
+
}
|
|
175
|
+
await writeFile(fullPath, content, 'utf-8');
|
|
176
|
+
console.log(` ✓ ${filePath}`);
|
|
177
|
+
}
|
|
178
|
+
console.log(`\n✅ MCP server generated successfully!\n`);
|
|
179
|
+
console.log(`Next steps:`);
|
|
180
|
+
console.log(` cd ${outputDir}`);
|
|
181
|
+
console.log(` npm install`);
|
|
182
|
+
console.log(` npm run build`);
|
|
183
|
+
console.log(` npm run start:http # For Cursor/HTTP transport`);
|
|
184
|
+
console.log(` npm start # For Claude Desktop/stdio transport`);
|
|
185
|
+
if (values.emcy) {
|
|
186
|
+
console.log(`\nEmcy Telemetry:`);
|
|
187
|
+
console.log(` Set EMCY_API_KEY in .env to enable telemetry.`);
|
|
188
|
+
console.log(` Get your API key at https://emcy.ai/dashboard`);
|
|
189
|
+
}
|
|
190
|
+
console.log('');
|
|
191
|
+
process.exit(0);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
console.error('\nError generating MCP server:', error instanceof Error ? error.message : error);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async function loadSpec(urlOrPath) {
|
|
199
|
+
// Check if it's a URL
|
|
200
|
+
if (urlOrPath.startsWith('http://') || urlOrPath.startsWith('https://')) {
|
|
201
|
+
const response = await fetch(urlOrPath);
|
|
202
|
+
if (!response.ok) {
|
|
203
|
+
throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
|
|
204
|
+
}
|
|
205
|
+
const contentType = response.headers.get('content-type') || '';
|
|
206
|
+
if (contentType.includes('yaml') || urlOrPath.match(/\.ya?ml$/i)) {
|
|
207
|
+
// Return as string for YAML parsing by swagger-parser
|
|
208
|
+
return await response.text();
|
|
209
|
+
}
|
|
210
|
+
return (await response.json());
|
|
211
|
+
}
|
|
212
|
+
// It's a file path
|
|
213
|
+
const resolved = resolve(urlOrPath);
|
|
214
|
+
if (!existsSync(resolved)) {
|
|
215
|
+
throw new Error(`File not found: ${resolved}`);
|
|
216
|
+
}
|
|
217
|
+
const content = await readFile(resolved, 'utf-8');
|
|
218
|
+
// Try to parse as JSON first
|
|
219
|
+
if (resolved.endsWith('.json')) {
|
|
220
|
+
return JSON.parse(content);
|
|
221
|
+
}
|
|
222
|
+
// Return as string for YAML parsing
|
|
223
|
+
return content;
|
|
224
|
+
}
|
|
225
|
+
function slugify(text) {
|
|
226
|
+
return text
|
|
227
|
+
.toLowerCase()
|
|
228
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
229
|
+
.replace(/^-|-$/g, '');
|
|
230
|
+
}
|
|
231
|
+
main().catch((error) => {
|
|
232
|
+
console.error('Fatal error:', error);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
});
|
|
235
|
+
//# 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":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Generator - Generates MCP server code from tool definitions
|
|
3
|
+
*/
|
|
4
|
+
import type { McpToolDefinition, GeneratorOptions, GeneratedFiles, SecurityScheme } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generate a complete MCP server from tool definitions
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateMcpServer(tools: McpToolDefinition[], options: GeneratorOptions, securitySchemes?: Record<string, SecurityScheme>): GeneratedFiles;
|
|
9
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EAAE,EAC1B,OAAO,EAAE,gBAAgB,EACzB,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAM,GACnD,cAAc,CAWhB"}
|