api2ai 1.0.1
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 +189 -0
- package/bun.lock +17 -0
- package/example-petstore/.env.example +14 -0
- package/example-petstore/README.md +145 -0
- package/example-petstore/bun.lock +387 -0
- package/example-petstore/package.json +19 -0
- package/example-petstore/src/http-client.js +120 -0
- package/example-petstore/src/index.js +493 -0
- package/example-petstore/src/tools-config.js +247 -0
- package/example.js +164 -0
- package/generate-mcp-use-server.js +832 -0
- package/package.json +31 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// Tool configurations extracted from OpenAPI spec
|
|
2
|
+
// Generated: 2025-12-30T23:36:57.080Z
|
|
3
|
+
|
|
4
|
+
export const toolConfigs = [
|
|
5
|
+
{
|
|
6
|
+
"name": "addPet",
|
|
7
|
+
"description": "Add a new pet to the store.",
|
|
8
|
+
"method": "post",
|
|
9
|
+
"pathTemplate": "/pet",
|
|
10
|
+
"executionParameters": [],
|
|
11
|
+
"requestBodyContentType": "application/json",
|
|
12
|
+
"baseUrl": "/api/v3"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "updatePet",
|
|
16
|
+
"description": "Update an existing pet.",
|
|
17
|
+
"method": "put",
|
|
18
|
+
"pathTemplate": "/pet",
|
|
19
|
+
"executionParameters": [],
|
|
20
|
+
"requestBodyContentType": "application/json",
|
|
21
|
+
"baseUrl": "/api/v3"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "findPetsByStatus",
|
|
25
|
+
"description": "Finds Pets by status.",
|
|
26
|
+
"method": "get",
|
|
27
|
+
"pathTemplate": "/pet/findByStatus",
|
|
28
|
+
"executionParameters": [
|
|
29
|
+
{
|
|
30
|
+
"name": "status",
|
|
31
|
+
"in": "query"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"baseUrl": "/api/v3"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "findPetsByTags",
|
|
38
|
+
"description": "Finds Pets by tags.",
|
|
39
|
+
"method": "get",
|
|
40
|
+
"pathTemplate": "/pet/findByTags",
|
|
41
|
+
"executionParameters": [
|
|
42
|
+
{
|
|
43
|
+
"name": "tags",
|
|
44
|
+
"in": "query"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"baseUrl": "/api/v3"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "getPetById",
|
|
51
|
+
"description": "Find pet by ID.",
|
|
52
|
+
"method": "get",
|
|
53
|
+
"pathTemplate": "/pet/{petId}",
|
|
54
|
+
"executionParameters": [
|
|
55
|
+
{
|
|
56
|
+
"name": "petId",
|
|
57
|
+
"in": "path"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"baseUrl": "/api/v3"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "updatePetWithForm",
|
|
64
|
+
"description": "Updates a pet in the store with form data.",
|
|
65
|
+
"method": "post",
|
|
66
|
+
"pathTemplate": "/pet/{petId}",
|
|
67
|
+
"executionParameters": [
|
|
68
|
+
{
|
|
69
|
+
"name": "petId",
|
|
70
|
+
"in": "path"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "name",
|
|
74
|
+
"in": "query"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "status",
|
|
78
|
+
"in": "query"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"baseUrl": "/api/v3"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "deletePet",
|
|
85
|
+
"description": "Deletes a pet.",
|
|
86
|
+
"method": "delete",
|
|
87
|
+
"pathTemplate": "/pet/{petId}",
|
|
88
|
+
"executionParameters": [
|
|
89
|
+
{
|
|
90
|
+
"name": "api_key",
|
|
91
|
+
"in": "header"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "petId",
|
|
95
|
+
"in": "path"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"baseUrl": "/api/v3"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "uploadFile",
|
|
102
|
+
"description": "Uploads an image.",
|
|
103
|
+
"method": "post",
|
|
104
|
+
"pathTemplate": "/pet/{petId}/uploadImage",
|
|
105
|
+
"executionParameters": [
|
|
106
|
+
{
|
|
107
|
+
"name": "petId",
|
|
108
|
+
"in": "path"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "additionalMetadata",
|
|
112
|
+
"in": "query"
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"requestBodyContentType": "application/octet-stream",
|
|
116
|
+
"baseUrl": "/api/v3"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "getInventory",
|
|
120
|
+
"description": "Returns pet inventories by status.",
|
|
121
|
+
"method": "get",
|
|
122
|
+
"pathTemplate": "/store/inventory",
|
|
123
|
+
"executionParameters": [],
|
|
124
|
+
"baseUrl": "/api/v3"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "placeOrder",
|
|
128
|
+
"description": "Place an order for a pet.",
|
|
129
|
+
"method": "post",
|
|
130
|
+
"pathTemplate": "/store/order",
|
|
131
|
+
"executionParameters": [],
|
|
132
|
+
"requestBodyContentType": "application/json",
|
|
133
|
+
"baseUrl": "/api/v3"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "getOrderById",
|
|
137
|
+
"description": "Find purchase order by ID.",
|
|
138
|
+
"method": "get",
|
|
139
|
+
"pathTemplate": "/store/order/{orderId}",
|
|
140
|
+
"executionParameters": [
|
|
141
|
+
{
|
|
142
|
+
"name": "orderId",
|
|
143
|
+
"in": "path"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"baseUrl": "/api/v3"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "deleteOrder",
|
|
150
|
+
"description": "Delete purchase order by identifier.",
|
|
151
|
+
"method": "delete",
|
|
152
|
+
"pathTemplate": "/store/order/{orderId}",
|
|
153
|
+
"executionParameters": [
|
|
154
|
+
{
|
|
155
|
+
"name": "orderId",
|
|
156
|
+
"in": "path"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"baseUrl": "/api/v3"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "createUser",
|
|
163
|
+
"description": "Create user.",
|
|
164
|
+
"method": "post",
|
|
165
|
+
"pathTemplate": "/user",
|
|
166
|
+
"executionParameters": [],
|
|
167
|
+
"requestBodyContentType": "application/json",
|
|
168
|
+
"baseUrl": "/api/v3"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"name": "createUsersWithListInput",
|
|
172
|
+
"description": "Creates list of users with given input array.",
|
|
173
|
+
"method": "post",
|
|
174
|
+
"pathTemplate": "/user/createWithList",
|
|
175
|
+
"executionParameters": [],
|
|
176
|
+
"requestBodyContentType": "application/json",
|
|
177
|
+
"baseUrl": "/api/v3"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "loginUser",
|
|
181
|
+
"description": "Logs user into the system.",
|
|
182
|
+
"method": "get",
|
|
183
|
+
"pathTemplate": "/user/login",
|
|
184
|
+
"executionParameters": [
|
|
185
|
+
{
|
|
186
|
+
"name": "username",
|
|
187
|
+
"in": "query"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "password",
|
|
191
|
+
"in": "query"
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
"baseUrl": "/api/v3"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "logoutUser",
|
|
198
|
+
"description": "Logs out current logged in user session.",
|
|
199
|
+
"method": "get",
|
|
200
|
+
"pathTemplate": "/user/logout",
|
|
201
|
+
"executionParameters": [],
|
|
202
|
+
"baseUrl": "/api/v3"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"name": "getUserByName",
|
|
206
|
+
"description": "Get user by user name.",
|
|
207
|
+
"method": "get",
|
|
208
|
+
"pathTemplate": "/user/{username}",
|
|
209
|
+
"executionParameters": [
|
|
210
|
+
{
|
|
211
|
+
"name": "username",
|
|
212
|
+
"in": "path"
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
"baseUrl": "/api/v3"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "updateUser",
|
|
219
|
+
"description": "Update user resource.",
|
|
220
|
+
"method": "put",
|
|
221
|
+
"pathTemplate": "/user/{username}",
|
|
222
|
+
"executionParameters": [
|
|
223
|
+
{
|
|
224
|
+
"name": "username",
|
|
225
|
+
"in": "path"
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
"requestBodyContentType": "application/json",
|
|
229
|
+
"baseUrl": "/api/v3"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"name": "deleteUser",
|
|
233
|
+
"description": "Delete user resource.",
|
|
234
|
+
"method": "delete",
|
|
235
|
+
"pathTemplate": "/user/{username}",
|
|
236
|
+
"executionParameters": [
|
|
237
|
+
{
|
|
238
|
+
"name": "username",
|
|
239
|
+
"in": "path"
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
"baseUrl": "/api/v3"
|
|
243
|
+
}
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
// Create a map for quick lookup
|
|
247
|
+
export const toolConfigMap = new Map(toolConfigs.map(t => [t.name, t]));
|
package/example.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Programmatic usage of the OpenAPI to MCP-Use generator
|
|
3
|
+
*
|
|
4
|
+
* This script demonstrates various ways to use the generator.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { generateMcpServer, extractTools, loadOpenApiSpec } from './generate-mcp-use-server.js';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Example 1: Generate from a remote URL
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
async function generateFromUrl() {
|
|
14
|
+
console.log('Example 1: Generate from URL\n');
|
|
15
|
+
|
|
16
|
+
const result = await generateMcpServer(
|
|
17
|
+
'https://petstore3.swagger.io/api/v3/openapi.json',
|
|
18
|
+
'./petstore-mcp',
|
|
19
|
+
{
|
|
20
|
+
serverName: 'petstore-api',
|
|
21
|
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
22
|
+
port: 3000,
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
console.log('Generated tools:', result.tools.slice(0, 5), '...');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Example 2: Generate with filtering
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
async function generateWithFiltering() {
|
|
34
|
+
console.log('Example 2: Generate with filtering\n');
|
|
35
|
+
|
|
36
|
+
const result = await generateMcpServer(
|
|
37
|
+
'https://petstore3.swagger.io/api/v3/openapi.json',
|
|
38
|
+
'./petstore-readonly',
|
|
39
|
+
{
|
|
40
|
+
serverName: 'petstore-readonly',
|
|
41
|
+
// Only include GET endpoints (read-only)
|
|
42
|
+
filterFn: (tool) => tool.method.toLowerCase() === 'get',
|
|
43
|
+
port: 3001,
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
console.log(`Generated ${result.toolCount} read-only tools`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Example 3: Extract tools without generating server
|
|
52
|
+
// ============================================================================
|
|
53
|
+
|
|
54
|
+
async function extractToolsOnly() {
|
|
55
|
+
console.log('Example 3: Extract tools only\n');
|
|
56
|
+
|
|
57
|
+
const spec = await loadOpenApiSpec('https://petstore3.swagger.io/api/v3/openapi.json');
|
|
58
|
+
|
|
59
|
+
console.log(`API: ${spec.info.title} v${spec.info.version}`);
|
|
60
|
+
|
|
61
|
+
const tools = extractTools(spec, {
|
|
62
|
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
63
|
+
// Exclude dangerous operations
|
|
64
|
+
excludeOperationIds: ['deletePet', 'deleteOrder', 'deleteUser'],
|
|
65
|
+
// Only include pet-related endpoints
|
|
66
|
+
filterFn: (tool) => tool.pathTemplate.includes('/pet'),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log('\nExtracted pet-related tools:');
|
|
70
|
+
tools.forEach(tool => {
|
|
71
|
+
console.log(` ${tool.method.toUpperCase().padEnd(6)} ${tool.pathTemplate}`);
|
|
72
|
+
console.log(` → ${tool.name}: ${tool.description}`);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Example 4: Generate from local file
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
async function generateFromLocalFile() {
|
|
81
|
+
console.log('Example 4: Generate from local file\n');
|
|
82
|
+
|
|
83
|
+
// This would work with a local file:
|
|
84
|
+
// const result = await generateMcpServer(
|
|
85
|
+
// './my-api-spec.yaml',
|
|
86
|
+
// './my-api-mcp',
|
|
87
|
+
// {
|
|
88
|
+
// serverName: 'my-api',
|
|
89
|
+
// port: 3002,
|
|
90
|
+
// }
|
|
91
|
+
// );
|
|
92
|
+
|
|
93
|
+
console.log('(Skipped - requires local file)');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Example 5: Advanced - Custom tool processing
|
|
98
|
+
// ============================================================================
|
|
99
|
+
|
|
100
|
+
async function advancedUsage() {
|
|
101
|
+
console.log('Example 5: Advanced tool processing\n');
|
|
102
|
+
|
|
103
|
+
const spec = await loadOpenApiSpec('https://petstore3.swagger.io/api/v3/openapi.json');
|
|
104
|
+
const tools = extractTools(spec);
|
|
105
|
+
|
|
106
|
+
// Analyze the tools
|
|
107
|
+
const methodCounts = {};
|
|
108
|
+
const tagCounts = {};
|
|
109
|
+
|
|
110
|
+
tools.forEach(tool => {
|
|
111
|
+
methodCounts[tool.method] = (methodCounts[tool.method] || 0) + 1;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
console.log('Tools by HTTP method:');
|
|
115
|
+
Object.entries(methodCounts)
|
|
116
|
+
.sort((a, b) => b[1] - a[1])
|
|
117
|
+
.forEach(([method, count]) => {
|
|
118
|
+
console.log(` ${method.toUpperCase()}: ${count} tools`);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
console.log('\nTools with request body:',
|
|
122
|
+
tools.filter(t => t.requestBodyContentType).length);
|
|
123
|
+
|
|
124
|
+
console.log('Tools requiring path params:',
|
|
125
|
+
tools.filter(t => t.executionParameters.some(p => p.in === 'path')).length);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Run examples
|
|
130
|
+
// ============================================================================
|
|
131
|
+
|
|
132
|
+
async function main() {
|
|
133
|
+
const example = process.argv[2] || 'all';
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
switch (example) {
|
|
137
|
+
case '1':
|
|
138
|
+
await generateFromUrl();
|
|
139
|
+
break;
|
|
140
|
+
case '2':
|
|
141
|
+
await generateWithFiltering();
|
|
142
|
+
break;
|
|
143
|
+
case '3':
|
|
144
|
+
await extractToolsOnly();
|
|
145
|
+
break;
|
|
146
|
+
case '4':
|
|
147
|
+
await generateFromLocalFile();
|
|
148
|
+
break;
|
|
149
|
+
case '5':
|
|
150
|
+
await advancedUsage();
|
|
151
|
+
break;
|
|
152
|
+
case 'all':
|
|
153
|
+
default:
|
|
154
|
+
// Just run the analysis example by default
|
|
155
|
+
await advancedUsage();
|
|
156
|
+
console.log('\n---\nRun specific example with: node example.js [1-5]');
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error('Error:', error.message);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
main();
|