@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Emcy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @emcy/openapi-to-mcp
|
|
2
|
+
|
|
3
|
+
Convert OpenAPI specifications to MCP (Model Context Protocol) servers in seconds.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@emcy/openapi-to-mcp)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## What is this?
|
|
9
|
+
|
|
10
|
+
This CLI tool takes an OpenAPI specification (Swagger) and generates a fully functional MCP server that exposes your API endpoints as AI-callable tools.
|
|
11
|
+
|
|
12
|
+
**Use cases:**
|
|
13
|
+
- Let AI assistants (Claude, Cursor, etc.) interact with your REST APIs
|
|
14
|
+
- Create MCP servers without writing code
|
|
15
|
+
- Add observability to AI tool usage with Emcy telemetry
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Generate from a URL
|
|
21
|
+
npx @emcy/openapi-to-mcp generate --url https://petstore.swagger.io/v2/swagger.json
|
|
22
|
+
|
|
23
|
+
# Generate from a local file
|
|
24
|
+
npx @emcy/openapi-to-mcp generate --url ./openapi.yaml --name my-api
|
|
25
|
+
|
|
26
|
+
# Generate with Emcy telemetry enabled
|
|
27
|
+
npx @emcy/openapi-to-mcp generate --url ./api.json --name my-api --emcy
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
You can use it directly with `npx` (recommended) or install globally:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @emcy/openapi-to-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Commands
|
|
39
|
+
|
|
40
|
+
### `generate`
|
|
41
|
+
|
|
42
|
+
Generate an MCP server from an OpenAPI specification.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx @emcy/openapi-to-mcp generate [options]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Options:**
|
|
49
|
+
|
|
50
|
+
| Option | Short | Description |
|
|
51
|
+
|--------|-------|-------------|
|
|
52
|
+
| `--url` | `-u` | URL or file path to OpenAPI specification (required) |
|
|
53
|
+
| `--name` | `-n` | Name for the generated MCP server |
|
|
54
|
+
| `--output` | `-o` | Output directory (default: `./<name>-mcp-server`) |
|
|
55
|
+
| `--emcy` | `-e` | Enable Emcy telemetry integration |
|
|
56
|
+
| `--base-url` | `-b` | Override base URL for API calls |
|
|
57
|
+
| `--version` | | Version string for the server |
|
|
58
|
+
| `--force` | `-f` | Overwrite existing output directory |
|
|
59
|
+
|
|
60
|
+
### `validate`
|
|
61
|
+
|
|
62
|
+
Validate an OpenAPI specification.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx @emcy/openapi-to-mcp validate --url https://api.example.com/openapi.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Generated Server
|
|
69
|
+
|
|
70
|
+
The generated MCP server includes:
|
|
71
|
+
|
|
72
|
+
- **TypeScript source code** - Full type safety
|
|
73
|
+
- **HTTP transport** - For Cursor and web-based clients
|
|
74
|
+
- **Stdio transport** - For Claude Desktop
|
|
75
|
+
- **Security support** - API keys, Bearer tokens, OAuth2
|
|
76
|
+
- **Environment-based config** - `.env.example` with all settings
|
|
77
|
+
- **README** - Usage instructions
|
|
78
|
+
|
|
79
|
+
### Running the Generated Server
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cd my-api-mcp-server
|
|
83
|
+
npm install
|
|
84
|
+
npm run build
|
|
85
|
+
|
|
86
|
+
# For Cursor/HTTP clients
|
|
87
|
+
npm run start:http
|
|
88
|
+
|
|
89
|
+
# For Claude Desktop/stdio
|
|
90
|
+
npm start
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Using with Cursor
|
|
94
|
+
|
|
95
|
+
Add to your `~/.cursor/mcp.json`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"my-api": {
|
|
101
|
+
"url": "http://localhost:3000/mcp"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Using with Claude Desktop
|
|
108
|
+
|
|
109
|
+
Add to your Claude Desktop config:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
"my-api": {
|
|
115
|
+
"command": "node",
|
|
116
|
+
"args": ["/path/to/my-api-mcp-server/build/index.js"]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Emcy Telemetry
|
|
123
|
+
|
|
124
|
+
When you generate with `--emcy`, the server includes [@emcy/sdk](https://www.npmjs.com/package/@emcy/sdk) for telemetry:
|
|
125
|
+
|
|
126
|
+
- **Tool invocation tracking** - Every tool call is logged
|
|
127
|
+
- **Error monitoring** - Failures are captured with context
|
|
128
|
+
- **Performance metrics** - Latency and success rates
|
|
129
|
+
- **Dashboard** - View analytics at [emcy.ai](https://emcy.ai)
|
|
130
|
+
|
|
131
|
+
To enable telemetry, set these environment variables:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
EMCY_API_KEY=your-api-key-from-dashboard
|
|
135
|
+
EMCY_TELEMETRY_URL=https://api.emcy.ai/v1/telemetry
|
|
136
|
+
EMCY_MCP_SERVER_ID=mcp_xxxxxxxxxxxx
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Programmatic Usage
|
|
140
|
+
|
|
141
|
+
You can also use the library programmatically:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { parseOpenAPI, mapToMcpTools, generateMcpServer } from '@emcy/openapi-to-mcp';
|
|
145
|
+
|
|
146
|
+
// Parse an OpenAPI spec
|
|
147
|
+
const parsed = await parseOpenAPI('https://api.example.com/openapi.json');
|
|
148
|
+
|
|
149
|
+
// Map endpoints to MCP tools
|
|
150
|
+
const tools = mapToMcpTools(parsed.endpoints);
|
|
151
|
+
|
|
152
|
+
// Generate server files
|
|
153
|
+
const files = generateMcpServer(tools, {
|
|
154
|
+
name: 'my-api',
|
|
155
|
+
version: '1.0.0',
|
|
156
|
+
baseUrl: 'https://api.example.com',
|
|
157
|
+
emcyEnabled: true,
|
|
158
|
+
}, parsed.securitySchemes);
|
|
159
|
+
|
|
160
|
+
// files is a Record<string, string> of file paths to contents
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Supported OpenAPI Features
|
|
164
|
+
|
|
165
|
+
- ✅ OpenAPI 3.0 and 3.1
|
|
166
|
+
- ✅ Path, query, and header parameters
|
|
167
|
+
- ✅ Request bodies (JSON)
|
|
168
|
+
- ✅ API key authentication
|
|
169
|
+
- ✅ Bearer token authentication
|
|
170
|
+
- ✅ OAuth2 (client credentials)
|
|
171
|
+
- ✅ Multiple security schemes
|
|
172
|
+
- ⏳ File uploads (coming soon)
|
|
173
|
+
- ⏳ Webhooks (coming soon)
|
|
174
|
+
|
|
175
|
+
## Examples
|
|
176
|
+
|
|
177
|
+
### Petstore API
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npx @emcy/openapi-to-mcp generate \
|
|
181
|
+
--url https://petstore.swagger.io/v2/swagger.json \
|
|
182
|
+
--name petstore
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Local Development API
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npx @emcy/openapi-to-mcp generate \
|
|
189
|
+
--url http://localhost:5000/swagger/v1/swagger.json \
|
|
190
|
+
--name my-local-api \
|
|
191
|
+
--base-url http://localhost:5000
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### With Emcy Telemetry
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx @emcy/openapi-to-mcp generate \
|
|
198
|
+
--url ./openapi.yaml \
|
|
199
|
+
--name my-api \
|
|
200
|
+
--emcy \
|
|
201
|
+
--output ./mcp-servers/my-api
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT © [Emcy](https://emcy.ai)
|
|
207
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/generator.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generator tests - ensures MCP server code is correctly generated
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { generateMcpServer } from '../generator.js';
|
|
6
|
+
describe('generateMcpServer', () => {
|
|
7
|
+
const baseOptions = {
|
|
8
|
+
name: 'test-api',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
baseUrl: 'http://localhost:3000',
|
|
11
|
+
};
|
|
12
|
+
it('should generate all required files', () => {
|
|
13
|
+
const tools = [];
|
|
14
|
+
const files = generateMcpServer(tools, baseOptions);
|
|
15
|
+
expect(Object.keys(files)).toEqual([
|
|
16
|
+
'package.json',
|
|
17
|
+
'tsconfig.json',
|
|
18
|
+
'src/index.ts',
|
|
19
|
+
'src/transport.ts',
|
|
20
|
+
'.env.example',
|
|
21
|
+
'README.md',
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
it('should generate valid package.json', () => {
|
|
25
|
+
const files = generateMcpServer([], baseOptions);
|
|
26
|
+
const pkg = JSON.parse(files['package.json']);
|
|
27
|
+
expect(pkg.name).toBe('test-api');
|
|
28
|
+
expect(pkg.version).toBe('1.0.0');
|
|
29
|
+
expect(pkg.type).toBe('module');
|
|
30
|
+
expect(pkg.scripts.build).toBe('tsc');
|
|
31
|
+
expect(pkg.scripts['start:http']).toBe('node build/index.js --transport=streamable-http');
|
|
32
|
+
expect(pkg.dependencies['@modelcontextprotocol/sdk']).toBeDefined();
|
|
33
|
+
expect(pkg.dependencies.axios).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
it('should include @emcy/sdk when emcyEnabled', () => {
|
|
36
|
+
const files = generateMcpServer([], { ...baseOptions, emcyEnabled: true });
|
|
37
|
+
const pkg = JSON.parse(files['package.json']);
|
|
38
|
+
expect(pkg.dependencies['@emcy/sdk']).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
it('should use local SDK path when specified', () => {
|
|
41
|
+
const files = generateMcpServer([], {
|
|
42
|
+
...baseOptions,
|
|
43
|
+
emcyEnabled: true,
|
|
44
|
+
localSdkPath: '../emcy-sdk',
|
|
45
|
+
});
|
|
46
|
+
const pkg = JSON.parse(files['package.json']);
|
|
47
|
+
expect(pkg.dependencies['@emcy/sdk']).toBe('file:../emcy-sdk');
|
|
48
|
+
});
|
|
49
|
+
it('should generate tool definitions in server entry', () => {
|
|
50
|
+
const tools = [
|
|
51
|
+
{
|
|
52
|
+
name: 'getUsers',
|
|
53
|
+
description: 'Get all users',
|
|
54
|
+
inputSchema: { type: 'object', properties: {} },
|
|
55
|
+
httpMethod: 'get',
|
|
56
|
+
pathTemplate: '/users',
|
|
57
|
+
parameters: [],
|
|
58
|
+
securitySchemes: [],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'createUser',
|
|
62
|
+
description: 'Create a user',
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: { requestBody: { type: 'object' } },
|
|
66
|
+
required: ['requestBody'],
|
|
67
|
+
},
|
|
68
|
+
httpMethod: 'post',
|
|
69
|
+
pathTemplate: '/users',
|
|
70
|
+
parameters: [],
|
|
71
|
+
requestBodyContentType: 'application/json',
|
|
72
|
+
securitySchemes: [],
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
const files = generateMcpServer(tools, baseOptions);
|
|
76
|
+
const serverCode = files['src/index.ts'];
|
|
77
|
+
// Should contain tool definitions
|
|
78
|
+
expect(serverCode).toContain('["getUsers"');
|
|
79
|
+
expect(serverCode).toContain('name: "getUsers"');
|
|
80
|
+
expect(serverCode).toContain('description: "Get all users"');
|
|
81
|
+
expect(serverCode).toContain('method: "get"');
|
|
82
|
+
expect(serverCode).toContain('pathTemplate: "/users"');
|
|
83
|
+
expect(serverCode).toContain('["createUser"');
|
|
84
|
+
expect(serverCode).toContain('name: "createUser"');
|
|
85
|
+
expect(serverCode).toContain('requestBodyContentType: "application/json"');
|
|
86
|
+
});
|
|
87
|
+
it('should include Emcy telemetry code when enabled', () => {
|
|
88
|
+
const files = generateMcpServer([], { ...baseOptions, emcyEnabled: true });
|
|
89
|
+
const serverCode = files['src/index.ts'];
|
|
90
|
+
expect(serverCode).toContain("import { EmcyTelemetry } from '@emcy/sdk'");
|
|
91
|
+
expect(serverCode).toContain('new EmcyTelemetry({');
|
|
92
|
+
expect(serverCode).toContain('emcy.trace(');
|
|
93
|
+
});
|
|
94
|
+
it('should not include Emcy code when disabled', () => {
|
|
95
|
+
const files = generateMcpServer([], baseOptions);
|
|
96
|
+
const serverCode = files['src/index.ts'];
|
|
97
|
+
expect(serverCode).not.toContain('EmcyTelemetry');
|
|
98
|
+
expect(serverCode).not.toContain('emcy.trace');
|
|
99
|
+
});
|
|
100
|
+
it('should set correct base URL in server', () => {
|
|
101
|
+
const files = generateMcpServer([], {
|
|
102
|
+
...baseOptions,
|
|
103
|
+
baseUrl: 'https://api.example.com/v1',
|
|
104
|
+
});
|
|
105
|
+
const serverCode = files['src/index.ts'];
|
|
106
|
+
expect(serverCode).toContain('API_BASE_URL = process.env.API_BASE_URL || "https://api.example.com/v1"');
|
|
107
|
+
});
|
|
108
|
+
it('should include security schemes in generated code', () => {
|
|
109
|
+
const securitySchemes = {
|
|
110
|
+
apiKey: {
|
|
111
|
+
type: 'apiKey',
|
|
112
|
+
name: 'X-API-Key',
|
|
113
|
+
in: 'header',
|
|
114
|
+
},
|
|
115
|
+
bearerAuth: {
|
|
116
|
+
type: 'http',
|
|
117
|
+
scheme: 'bearer',
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
const tools = [
|
|
121
|
+
{
|
|
122
|
+
name: 'secureEndpoint',
|
|
123
|
+
description: 'A secure endpoint',
|
|
124
|
+
inputSchema: { type: 'object', properties: {} },
|
|
125
|
+
httpMethod: 'get',
|
|
126
|
+
pathTemplate: '/secure',
|
|
127
|
+
parameters: [],
|
|
128
|
+
securitySchemes: ['apiKey', 'bearerAuth'],
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
const files = generateMcpServer(tools, baseOptions, securitySchemes);
|
|
132
|
+
const serverCode = files['src/index.ts'];
|
|
133
|
+
expect(serverCode).toContain('"apiKey"');
|
|
134
|
+
expect(serverCode).toContain('"bearerAuth"');
|
|
135
|
+
expect(serverCode).toContain('applySecurityHeaders');
|
|
136
|
+
});
|
|
137
|
+
it('should generate proper path parameter handling', () => {
|
|
138
|
+
const tools = [
|
|
139
|
+
{
|
|
140
|
+
name: 'getUser',
|
|
141
|
+
description: 'Get user by ID',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: { id: { type: 'integer' } },
|
|
145
|
+
required: ['id'],
|
|
146
|
+
},
|
|
147
|
+
httpMethod: 'get',
|
|
148
|
+
pathTemplate: '/users/{id}',
|
|
149
|
+
parameters: [{ name: 'id', in: 'path', required: true, schema: { type: 'integer' } }],
|
|
150
|
+
securitySchemes: [],
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
const files = generateMcpServer(tools, baseOptions);
|
|
154
|
+
const serverCode = files['src/index.ts'];
|
|
155
|
+
expect(serverCode).toContain('pathTemplate: "/users/{id}"');
|
|
156
|
+
expect(serverCode).toContain('"in":"path"');
|
|
157
|
+
});
|
|
158
|
+
it('should generate README with correct server name', () => {
|
|
159
|
+
const files = generateMcpServer([], { ...baseOptions, name: 'my-awesome-api' });
|
|
160
|
+
const readme = files['README.md'];
|
|
161
|
+
expect(readme).toContain('# my-awesome-api');
|
|
162
|
+
expect(readme).toContain('my-awesome-api');
|
|
163
|
+
});
|
|
164
|
+
it('should generate .env.example with API URL', () => {
|
|
165
|
+
const files = generateMcpServer([], baseOptions);
|
|
166
|
+
const envExample = files['.env.example'];
|
|
167
|
+
expect(envExample).toContain('API_BASE_URL=');
|
|
168
|
+
expect(envExample).toContain('PORT=3000');
|
|
169
|
+
});
|
|
170
|
+
it('should generate .env.example with security credentials when needed', () => {
|
|
171
|
+
const tools = [
|
|
172
|
+
{
|
|
173
|
+
name: 'secureEndpoint',
|
|
174
|
+
description: 'Secure',
|
|
175
|
+
inputSchema: { type: 'object', properties: {} },
|
|
176
|
+
httpMethod: 'get',
|
|
177
|
+
pathTemplate: '/secure',
|
|
178
|
+
parameters: [],
|
|
179
|
+
securitySchemes: ['apiKeyAuth'],
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
const securitySchemes = {
|
|
183
|
+
apiKeyAuth: { type: 'apiKey', name: 'X-API-Key', in: 'header' },
|
|
184
|
+
};
|
|
185
|
+
const files = generateMcpServer(tools, baseOptions, securitySchemes);
|
|
186
|
+
const envExample = files['.env.example'];
|
|
187
|
+
expect(envExample).toContain('Security Credentials');
|
|
188
|
+
expect(envExample).toContain('API_KEY_APIKEYAUTH=');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('generator produces working TypeScript', () => {
|
|
192
|
+
it('should generate syntactically valid TypeScript (no obvious errors)', () => {
|
|
193
|
+
const tools = [
|
|
194
|
+
{
|
|
195
|
+
name: 'complexTool',
|
|
196
|
+
description: 'A tool with "quotes" and special chars: <>&',
|
|
197
|
+
inputSchema: {
|
|
198
|
+
type: 'object',
|
|
199
|
+
properties: {
|
|
200
|
+
name: { type: 'string', description: 'User\'s name' },
|
|
201
|
+
data: { type: 'object' },
|
|
202
|
+
},
|
|
203
|
+
required: ['name'],
|
|
204
|
+
},
|
|
205
|
+
httpMethod: 'post',
|
|
206
|
+
pathTemplate: '/complex/{id}/action',
|
|
207
|
+
parameters: [
|
|
208
|
+
{ name: 'id', in: 'path', required: true, schema: { type: 'string' } },
|
|
209
|
+
],
|
|
210
|
+
requestBodyContentType: 'application/json',
|
|
211
|
+
securitySchemes: ['auth'],
|
|
212
|
+
},
|
|
213
|
+
];
|
|
214
|
+
const files = generateMcpServer(tools, {
|
|
215
|
+
name: 'complex-api',
|
|
216
|
+
baseUrl: 'https://api.example.com',
|
|
217
|
+
emcyEnabled: true,
|
|
218
|
+
}, {
|
|
219
|
+
auth: { type: 'http', scheme: 'bearer' },
|
|
220
|
+
});
|
|
221
|
+
const serverCode = files['src/index.ts'];
|
|
222
|
+
// Should have balanced braces (basic syntax check)
|
|
223
|
+
const openBraces = (serverCode.match(/{/g) || []).length;
|
|
224
|
+
const closeBraces = (serverCode.match(/}/g) || []).length;
|
|
225
|
+
expect(openBraces).toBe(closeBraces);
|
|
226
|
+
// Should have balanced brackets
|
|
227
|
+
const openBrackets = (serverCode.match(/\[/g) || []).length;
|
|
228
|
+
const closeBrackets = (serverCode.match(/\]/g) || []).length;
|
|
229
|
+
expect(openBrackets).toBe(closeBrackets);
|
|
230
|
+
// Should have balanced parentheses
|
|
231
|
+
const openParens = (serverCode.match(/\(/g) || []).length;
|
|
232
|
+
const closeParens = (serverCode.match(/\)/g) || []).length;
|
|
233
|
+
expect(openParens).toBe(closeParens);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
//# sourceMappingURL=generator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.test.js","sourceRoot":"","sources":["../../src/__tests__/generator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|