rapidoc 11.0.0 → 12.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 +46 -31
- package/dist/rapidoc-min.js +1424 -213
- package/dist/rapidoc-static-min.js +13542 -0
- package/package.json +48 -34
- package/src/components/api-request.ts +869 -0
- package/src/components/api-response.ts +509 -0
- package/src/components/json-tree.ts +171 -0
- package/src/components/schema-base-element.ts +315 -0
- package/src/components/schema-table.ts +430 -0
- package/src/components/schema-tree.ts +386 -0
- package/src/components/tag-input.ts +184 -0
- package/src/index.js +6 -0
- package/src/oauth-receiver.ts +29 -0
- package/src/rapidoc-mini.ts +582 -0
- package/src/rapidoc.ts +1808 -0
- package/src/static/index.d.ts +149 -0
- package/src/static/index.js +62 -0
- package/src/static/navigation.js +497 -0
- package/src/static/render.js +490 -0
- package/src/static/serializer.js +216 -0
- package/src/styles/auth-styles.js +318 -0
- package/src/styles/border-styles.js +24 -0
- package/src/styles/css-bundle.js +129 -0
- package/src/styles/custom-styles.js +8 -0
- package/src/styles/dialog-box-styles.js +102 -0
- package/src/styles/endpoint-styles.js +559 -0
- package/src/styles/flex-styles.js +16 -0
- package/src/styles/font-styles.js +432 -0
- package/src/styles/info-styles.js +36 -0
- package/src/styles/input-styles.js +555 -0
- package/src/styles/layout-styles.js +396 -0
- package/src/styles/microlighter-styles.js +99 -0
- package/src/styles/nav-styles.js +609 -0
- package/src/styles/param-list-styles.js +261 -0
- package/src/styles/schema-styles.js +288 -0
- package/src/styles/tab-styles.js +106 -0
- package/src/styles/theme-tokens.js +582 -0
- package/src/templates/advanced-search-dialog-template.js +94 -0
- package/src/templates/api-response-template.js +219 -0
- package/src/templates/callback-template.js +86 -0
- package/src/templates/code-samples-template.js +52 -0
- package/src/templates/components-template.js +86 -0
- package/src/templates/downloads-template.js +85 -0
- package/src/templates/endpoint-template.js +386 -0
- package/src/templates/expanded-endpoint-template.js +266 -0
- package/src/templates/focused-endpoint-template.js +145 -0
- package/src/templates/header-template.js +92 -0
- package/src/templates/logo-template.js +21 -0
- package/src/templates/main-body-template.js +102 -0
- package/src/templates/navbar-template.js +489 -0
- package/src/templates/overview-template.js +104 -0
- package/src/templates/request-body-template.js +651 -0
- package/src/templates/request-params-template.js +474 -0
- package/src/templates/security-scheme-template.js +1263 -0
- package/src/templates/server-template.js +152 -0
- package/src/utils/auto-color-scheme.js +99 -0
- package/src/utils/bind-navbar.js +175 -0
- package/src/utils/color-utils.js +59 -0
- package/src/utils/common-utils.js +191 -0
- package/src/utils/curl-utils.js +123 -0
- package/src/utils/highlighter.js +416 -0
- package/src/utils/markdown-utils.js +110 -0
- package/src/utils/mcp/common.js +467 -0
- package/src/utils/mcp/generators/csharp.js +242 -0
- package/src/utils/mcp/generators/go.js +298 -0
- package/src/utils/mcp/generators/java.js +330 -0
- package/src/utils/mcp/generators/python.js +248 -0
- package/src/utils/mcp/generators/rust.js +281 -0
- package/src/utils/mcp/generators/typescript.js +290 -0
- package/src/utils/mcp-generator.js +143 -0
- package/src/utils/mock-interceptor.js +508 -0
- package/src/utils/oauth-utils.js +87 -0
- package/src/utils/request-utils.js +203 -0
- package/src/utils/response-utils.js +203 -0
- package/src/utils/sanitize.js +57 -0
- package/src/utils/schema-utils.js +1927 -0
- package/src/utils/slugger.js +189 -0
- package/src/utils/spec-parser.js +915 -0
- package/src/utils/url-utils.js +211 -0
- package/src/utils/xml-utils.js +61 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-file TypeScript MCP Server Generator
|
|
3
|
+
* Uses official @modelcontextprotocol/sdk and zod.
|
|
4
|
+
*/
|
|
5
|
+
import { toSnakeCase, estimateTokenCost } from "../common.js";
|
|
6
|
+
|
|
7
|
+
export function generateTypeScriptMcpServer(metadata, tools, resources, workflows, options = {}) {
|
|
8
|
+
const serverName = toSnakeCase(options.serverName || metadata.title || "rapidoc_mcp_server");
|
|
9
|
+
const budget = estimateTokenCost(tools, resources, workflows);
|
|
10
|
+
const defaultBaseUrl = metadata.servers?.[0]?.url || "http://localhost:3000";
|
|
11
|
+
|
|
12
|
+
const toolDefinitions = tools
|
|
13
|
+
.map((t) => {
|
|
14
|
+
// Build Zod schema properties
|
|
15
|
+
const zodProps = t.parameters
|
|
16
|
+
.map((p) => {
|
|
17
|
+
let zodType = "z.string()";
|
|
18
|
+
if (p.type === "integer" || p.type === "number") zodType = "z.number()";
|
|
19
|
+
else if (p.type === "boolean") zodType = "z.boolean()";
|
|
20
|
+
else if (p.type === "array") zodType = "z.array(z.string())";
|
|
21
|
+
else if (p.type === "object") zodType = "z.record(z.any())";
|
|
22
|
+
|
|
23
|
+
if (p.description) {
|
|
24
|
+
zodType += `.describe(${JSON.stringify(p.description)})`;
|
|
25
|
+
}
|
|
26
|
+
if (!p.required) {
|
|
27
|
+
zodType += ".optional()";
|
|
28
|
+
}
|
|
29
|
+
return ` ${JSON.stringify(p.name)}: ${zodType},`;
|
|
30
|
+
})
|
|
31
|
+
.join("\n");
|
|
32
|
+
|
|
33
|
+
const allZodProps = zodProps
|
|
34
|
+
? `${zodProps}\n apiKey: z.string().optional().describe('Optional Bearer API key override for multi-tenant sessions'),`
|
|
35
|
+
: ` apiKey: z.string().optional().describe('Optional Bearer API key override for multi-tenant sessions'),`;
|
|
36
|
+
|
|
37
|
+
const pathSubstitution = t.path.replace(/\{([^}]+)\}/g, '${encodeURIComponent(args["$1"])}');
|
|
38
|
+
|
|
39
|
+
const headerParams = t.parameters.filter((p) => p.in === "header");
|
|
40
|
+
const headerAppends = headerParams
|
|
41
|
+
.map(
|
|
42
|
+
(p) =>
|
|
43
|
+
` if (args[${JSON.stringify(p.name)}]) {\n headers[${JSON.stringify(p.name)}] = String(args[${JSON.stringify(p.name)}]);\n }`,
|
|
44
|
+
)
|
|
45
|
+
.join("\n");
|
|
46
|
+
|
|
47
|
+
return `
|
|
48
|
+
// Tool: ${t.name} (${t.method} ${t.path})
|
|
49
|
+
// ${t.isConsequential ? "⚠️ Consequential/Destructive action" : "Safe/Read-only action"}
|
|
50
|
+
server.tool(
|
|
51
|
+
${JSON.stringify(t.name)},
|
|
52
|
+
${JSON.stringify(t.description + (t.isConsequential ? " (Requires confirmation)" : ""))},
|
|
53
|
+
{
|
|
54
|
+
${allZodProps}
|
|
55
|
+
},
|
|
56
|
+
async (args: any) => {
|
|
57
|
+
const targetUrl = new URL(\`\${BASE_URL.replace(/\\/$/, '')}${pathSubstitution}\`);
|
|
58
|
+
let url = targetUrl.toString();
|
|
59
|
+
const queryParams = new URLSearchParams();
|
|
60
|
+
${t.parameters
|
|
61
|
+
.filter((p) => p.in === "query")
|
|
62
|
+
.map(
|
|
63
|
+
(p) =>
|
|
64
|
+
` if (args[${JSON.stringify(p.name)}] !== undefined) queryParams.set(${JSON.stringify(p.name)}, String(args[${JSON.stringify(p.name)}]));`,
|
|
65
|
+
)
|
|
66
|
+
.join("\n")}
|
|
67
|
+
const qs = queryParams.toString();
|
|
68
|
+
if (qs) url += (url.includes('?') ? '&' : '?') + qs;
|
|
69
|
+
|
|
70
|
+
const headers: Record<string, string> = {
|
|
71
|
+
'Accept': 'application/json',
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
};
|
|
74
|
+
${headerAppends ? "\n" + headerAppends + "\n" : ""} const resolvedKey = args?.apiKey || API_KEY;
|
|
75
|
+
if (resolvedKey) headers['Authorization'] = \`Bearer \${resolvedKey}\`;
|
|
76
|
+
|
|
77
|
+
const fetchOptions: RequestInit = {
|
|
78
|
+
method: ${JSON.stringify(t.method)},
|
|
79
|
+
headers,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
${
|
|
83
|
+
["POST", "PUT", "PATCH"].includes(t.method)
|
|
84
|
+
? ` const bodyPayload: Record<string, any> = {};
|
|
85
|
+
${t.parameters
|
|
86
|
+
.filter((p) => p.in === "body")
|
|
87
|
+
.map(
|
|
88
|
+
(p) =>
|
|
89
|
+
` if (args[${JSON.stringify(p.name)}] !== undefined) bodyPayload[${JSON.stringify(p.name)}] = args[${JSON.stringify(p.name)}];`,
|
|
90
|
+
)
|
|
91
|
+
.join("\n")}
|
|
92
|
+
if (Object.keys(bodyPayload).length > 0) {
|
|
93
|
+
fetchOptions.body = JSON.stringify(bodyPayload);
|
|
94
|
+
}`
|
|
95
|
+
: ""
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const response = await fetch(url, fetchOptions);
|
|
100
|
+
const text = await response.text();
|
|
101
|
+
let data = text;
|
|
102
|
+
try { data = JSON.parse(text); } catch {}
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: 'text', text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) }],
|
|
105
|
+
};
|
|
106
|
+
} catch (err: any) {
|
|
107
|
+
return {
|
|
108
|
+
isError: true,
|
|
109
|
+
content: [{ type: 'text', text: \`Error invoking ${t.name}: \${err.message}\` }],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
);`;
|
|
114
|
+
})
|
|
115
|
+
.join("\n");
|
|
116
|
+
|
|
117
|
+
const resourceDefinitions = resources
|
|
118
|
+
.map((r) => {
|
|
119
|
+
return `
|
|
120
|
+
// Resource: ${r.name} (${r.uri})
|
|
121
|
+
server.resource(
|
|
122
|
+
${JSON.stringify(r.name)},
|
|
123
|
+
${JSON.stringify(r.uri)},
|
|
124
|
+
async (uri) => {
|
|
125
|
+
const targetUrl = new URL(\`\${BASE_URL.replace(/\\/$/, '')}${r.path}\`);
|
|
126
|
+
const resolvedKey = uri.searchParams?.get('apiKey') || uri.searchParams?.get('api_key') || API_KEY;
|
|
127
|
+
if (uri.searchParams) {
|
|
128
|
+
uri.searchParams.forEach((val, key) => {
|
|
129
|
+
if (!['apikey', 'api_key'].includes(key.toLowerCase())) {
|
|
130
|
+
targetUrl.searchParams.set(key, val);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const headers: Record<string, string> = { 'Accept': ${JSON.stringify(r.mimeType)} };
|
|
135
|
+
if (resolvedKey) headers['Authorization'] = \`Bearer \${resolvedKey}\`;
|
|
136
|
+
|
|
137
|
+
const res = await fetch(targetUrl.toString(), { headers });
|
|
138
|
+
const text = await res.text();
|
|
139
|
+
return {
|
|
140
|
+
contents: [{
|
|
141
|
+
uri: uri.href,
|
|
142
|
+
text,
|
|
143
|
+
mimeType: ${JSON.stringify(r.mimeType)},
|
|
144
|
+
}],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
);`;
|
|
148
|
+
})
|
|
149
|
+
.join("\n");
|
|
150
|
+
|
|
151
|
+
const workflowDefinitions = workflows
|
|
152
|
+
.map((w) => {
|
|
153
|
+
const paramKeys = w.parameters ? Object.keys(w.parameters) : [];
|
|
154
|
+
const zodProps = paramKeys
|
|
155
|
+
.map(
|
|
156
|
+
(k) =>
|
|
157
|
+
` ${JSON.stringify(k)}: z.string().describe(${JSON.stringify(w.parameters[k].description || "")}),`,
|
|
158
|
+
)
|
|
159
|
+
.concat([
|
|
160
|
+
` apiKey: z.string().optional().describe('Optional Bearer API key override for multi-tenant sessions'),`,
|
|
161
|
+
])
|
|
162
|
+
.join("\n");
|
|
163
|
+
const firstParam = paramKeys[0] || "id";
|
|
164
|
+
|
|
165
|
+
return `
|
|
166
|
+
// Composite Workflow: ${w.name}
|
|
167
|
+
// Collapses multi-step atomic REST calls into 1 tool call
|
|
168
|
+
server.tool(
|
|
169
|
+
${JSON.stringify(w.name)},
|
|
170
|
+
${JSON.stringify(w.description || "Composite workflow")},
|
|
171
|
+
{
|
|
172
|
+
${zodProps}
|
|
173
|
+
},
|
|
174
|
+
async (args: any) => {
|
|
175
|
+
const results: Record<string, any> = {};
|
|
176
|
+
const headers: Record<string, string> = { 'Accept': 'application/json' };
|
|
177
|
+
const resolvedKey = args?.apiKey || API_KEY;
|
|
178
|
+
if (resolvedKey) headers['Authorization'] = \`Bearer \${resolvedKey}\`;
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
${(w.steps || [])
|
|
182
|
+
.map((s, idx) => {
|
|
183
|
+
return ` // Step ${idx + 1}: ${s.call}
|
|
184
|
+
const stepUrl_${idx} = \`\${BASE_URL.replace(/\\/$/, '')}/api/\${encodeURIComponent(args[${JSON.stringify(firstParam)}] || '')}\`;
|
|
185
|
+
const resp_${idx} = await fetch(stepUrl_${idx}, { headers });
|
|
186
|
+
results[${JSON.stringify(s.call)}] = await resp_${idx}.json();`;
|
|
187
|
+
})
|
|
188
|
+
.join("\n")}
|
|
189
|
+
return {
|
|
190
|
+
content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
|
|
191
|
+
};
|
|
192
|
+
} catch (err: any) {
|
|
193
|
+
return {
|
|
194
|
+
isError: true,
|
|
195
|
+
content: [{ type: 'text', text: \`Workflow ${w.name} failed: \${err.message}\` }],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
);`;
|
|
200
|
+
})
|
|
201
|
+
.join("\n");
|
|
202
|
+
|
|
203
|
+
return `/**
|
|
204
|
+
* Auto-generated by RapiDoc Curated MCP Generator
|
|
205
|
+
* Spec: ${metadata.title} (v${metadata.version})
|
|
206
|
+
*
|
|
207
|
+
* [MULTI-TENANCY & AUTHENTICATION]
|
|
208
|
+
* - Local Stdio Mode: Claude Desktop, Cursor, and local agents use API_KEY from environment.
|
|
209
|
+
* - Multi-Tenant / Agent Mode: When running in a shared service, the calling AI agent can pass
|
|
210
|
+
* per-session credentials directly in the \`apiKey\` parameter of any tool.
|
|
211
|
+
*
|
|
212
|
+
* [TOKEN BUDGET DIAGNOSTIC]
|
|
213
|
+
* - Total Tools: ${budget.totalTools}
|
|
214
|
+
* - Total Resources: ${budget.totalResources}
|
|
215
|
+
* - Total Workflows: ${budget.totalWorkflows}
|
|
216
|
+
* - Estimated Prompt Context Overhead: ~${budget.estimatedTokens.toLocaleString()} tokens/turn
|
|
217
|
+
${budget.warnings.map((w) => ` * - ⚠️ ${w}`).join("\n")}
|
|
218
|
+
*
|
|
219
|
+
* [HOW TO RUN]
|
|
220
|
+
* 1. npm install @modelcontextprotocol/sdk zod
|
|
221
|
+
* 2. API_KEY="your-key" npx tsx server.ts
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
225
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
226
|
+
import { z } from 'zod';
|
|
227
|
+
|
|
228
|
+
const API_KEY = process.env.API_KEY || '';
|
|
229
|
+
const BASE_URL = process.env.API_BASE_URL || ${JSON.stringify(defaultBaseUrl)};
|
|
230
|
+
|
|
231
|
+
const server = new McpServer({
|
|
232
|
+
name: ${JSON.stringify(serverName)},
|
|
233
|
+
version: ${JSON.stringify(metadata.version)},
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
${resourceDefinitions}
|
|
237
|
+
${toolDefinitions}
|
|
238
|
+
${workflowDefinitions}
|
|
239
|
+
|
|
240
|
+
async function main() {
|
|
241
|
+
const transport = new StdioServerTransport();
|
|
242
|
+
await server.connect(transport);
|
|
243
|
+
console.error(\`[MCP] ${serverName} running on stdio\`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
main().catch((err) => {
|
|
247
|
+
console.error('[MCP] Fatal error running server:', err);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
});
|
|
250
|
+
`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function generateTypeScriptFiles(serverCode, metadata, options = {}) {
|
|
254
|
+
const packageJson = {
|
|
255
|
+
name: toSnakeCase(options.serverName || metadata.title || "rapidoc-mcp-server"),
|
|
256
|
+
version: metadata.version || "1.0.0",
|
|
257
|
+
type: "module",
|
|
258
|
+
scripts: {
|
|
259
|
+
start: "npx tsx server.ts",
|
|
260
|
+
},
|
|
261
|
+
dependencies: {
|
|
262
|
+
"@modelcontextprotocol/sdk": "^1.6.0",
|
|
263
|
+
zod: "^3.24.0",
|
|
264
|
+
},
|
|
265
|
+
devDependencies: {
|
|
266
|
+
tsx: "^4.19.0",
|
|
267
|
+
typescript: "^5.7.0",
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const readme = `# ${metadata.title} - MCP Server (TypeScript)
|
|
272
|
+
|
|
273
|
+
Auto-generated by RapiDoc Curated MCP Generator.
|
|
274
|
+
|
|
275
|
+
### Prerequisites
|
|
276
|
+
- Node.js 18+
|
|
277
|
+
- \`npm install\`
|
|
278
|
+
|
|
279
|
+
### Running the Server
|
|
280
|
+
\`\`\`bash
|
|
281
|
+
API_KEY="your-key" npm start
|
|
282
|
+
\`\`\`
|
|
283
|
+
`;
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
"server.ts": serverCode,
|
|
287
|
+
"package.json": JSON.stringify(packageJson, null, 2),
|
|
288
|
+
"README.md": readme,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) Server Generator for RapiDoc
|
|
3
|
+
*
|
|
4
|
+
* Implements client-side, zero-runtime-dependency translation from OpenAPI specs
|
|
5
|
+
* into curated, token-efficient MCP servers across multiple language ecosystems:
|
|
6
|
+
* - TypeScript (@modelcontextprotocol/sdk + zod)
|
|
7
|
+
* - Python (fastmcp + standard urllib)
|
|
8
|
+
* - Go (mark3labs/mcp-go)
|
|
9
|
+
* - C# (.NET / ModelContextProtocol.NET)
|
|
10
|
+
* - Rust (mcp-sdk / rmcp)
|
|
11
|
+
* - Java (Spring AI MCP)
|
|
12
|
+
*
|
|
13
|
+
* Honors primary `x-mcp` extensions and compatibility aliases from Redocly,
|
|
14
|
+
* Scalar, OpenAI (x-openai-isConsequential), and Speakeasy.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
AUTH_TRANSPORT_HEADERS,
|
|
19
|
+
VALID_MCP_TARGETS,
|
|
20
|
+
MCP_TARGET_LABELS,
|
|
21
|
+
parseMcpTargets,
|
|
22
|
+
toSnakeCase,
|
|
23
|
+
toPascalCase,
|
|
24
|
+
toCamelCase,
|
|
25
|
+
sanitizeDescription,
|
|
26
|
+
deriveToolName,
|
|
27
|
+
extractParameters,
|
|
28
|
+
extractMcpOperations,
|
|
29
|
+
estimateTokenCost,
|
|
30
|
+
generateHostConfigs,
|
|
31
|
+
} from "./mcp/common.js";
|
|
32
|
+
|
|
33
|
+
import { extractMcpOperations, estimateTokenCost, generateHostConfigs } from "./mcp/common.js";
|
|
34
|
+
import {
|
|
35
|
+
generateTypeScriptMcpServer,
|
|
36
|
+
generateTypeScriptFiles,
|
|
37
|
+
} from "./mcp/generators/typescript.js";
|
|
38
|
+
import { generatePythonFastMcpServer, generatePythonFiles } from "./mcp/generators/python.js";
|
|
39
|
+
import { generateGoMcpServer, generateGoFiles } from "./mcp/generators/go.js";
|
|
40
|
+
import { generateCSharpMcpServer, generateCSharpFiles } from "./mcp/generators/csharp.js";
|
|
41
|
+
import { generateRustMcpServer, generateRustFiles } from "./mcp/generators/rust.js";
|
|
42
|
+
import { generateJavaMcpServer, generateJavaFiles } from "./mcp/generators/java.js";
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
generateTypeScriptMcpServer,
|
|
46
|
+
generatePythonFastMcpServer,
|
|
47
|
+
generateGoMcpServer,
|
|
48
|
+
generateCSharpMcpServer,
|
|
49
|
+
generateRustMcpServer,
|
|
50
|
+
generateJavaMcpServer,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Main orchestrator: extracts MCP operations, computes budget, and generates
|
|
55
|
+
* language-specific server implementation and packaging manifests.
|
|
56
|
+
*
|
|
57
|
+
* @param {object} parsedSpec Raw or parsed OpenAPI specification object
|
|
58
|
+
* @param {object} options Target language, server name, and filtering options
|
|
59
|
+
* @returns {object} { target, serverCode, hostConfig, budget, files, extracted }
|
|
60
|
+
*/
|
|
61
|
+
export function generateMcpServer(parsedSpec, options = {}) {
|
|
62
|
+
const rawTarget = (options.target || "typescript").toLowerCase();
|
|
63
|
+
const target = rawTarget === "c#" ? "csharp" : rawTarget;
|
|
64
|
+
const extracted = extractMcpOperations(parsedSpec, options);
|
|
65
|
+
const budget = estimateTokenCost(extracted.tools, extracted.resources, extracted.workflows);
|
|
66
|
+
const hostConfigs = generateHostConfigs(options.serverName || extracted.metadata.title, {
|
|
67
|
+
target,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
let serverCode;
|
|
71
|
+
let targetFiles;
|
|
72
|
+
|
|
73
|
+
if (target === "python") {
|
|
74
|
+
serverCode = generatePythonFastMcpServer(
|
|
75
|
+
extracted.metadata,
|
|
76
|
+
extracted.tools,
|
|
77
|
+
extracted.resources,
|
|
78
|
+
extracted.workflows,
|
|
79
|
+
options,
|
|
80
|
+
);
|
|
81
|
+
targetFiles = generatePythonFiles(serverCode, extracted.metadata, options);
|
|
82
|
+
} else if (target === "go") {
|
|
83
|
+
serverCode = generateGoMcpServer(
|
|
84
|
+
extracted.metadata,
|
|
85
|
+
extracted.tools,
|
|
86
|
+
extracted.resources,
|
|
87
|
+
extracted.workflows,
|
|
88
|
+
options,
|
|
89
|
+
);
|
|
90
|
+
targetFiles = generateGoFiles(serverCode, extracted.metadata, options);
|
|
91
|
+
} else if (target === "csharp") {
|
|
92
|
+
serverCode = generateCSharpMcpServer(
|
|
93
|
+
extracted.metadata,
|
|
94
|
+
extracted.tools,
|
|
95
|
+
extracted.resources,
|
|
96
|
+
extracted.workflows,
|
|
97
|
+
options,
|
|
98
|
+
);
|
|
99
|
+
targetFiles = generateCSharpFiles(serverCode, extracted.metadata, options);
|
|
100
|
+
} else if (target === "rust") {
|
|
101
|
+
serverCode = generateRustMcpServer(
|
|
102
|
+
extracted.metadata,
|
|
103
|
+
extracted.tools,
|
|
104
|
+
extracted.resources,
|
|
105
|
+
extracted.workflows,
|
|
106
|
+
options,
|
|
107
|
+
);
|
|
108
|
+
targetFiles = generateRustFiles(serverCode, extracted.metadata, options);
|
|
109
|
+
} else if (target === "java") {
|
|
110
|
+
serverCode = generateJavaMcpServer(
|
|
111
|
+
extracted.metadata,
|
|
112
|
+
extracted.tools,
|
|
113
|
+
extracted.resources,
|
|
114
|
+
extracted.workflows,
|
|
115
|
+
options,
|
|
116
|
+
);
|
|
117
|
+
targetFiles = generateJavaFiles(serverCode, extracted.metadata, options);
|
|
118
|
+
} else {
|
|
119
|
+
// Default: TypeScript
|
|
120
|
+
serverCode = generateTypeScriptMcpServer(
|
|
121
|
+
extracted.metadata,
|
|
122
|
+
extracted.tools,
|
|
123
|
+
extracted.resources,
|
|
124
|
+
extracted.workflows,
|
|
125
|
+
options,
|
|
126
|
+
);
|
|
127
|
+
targetFiles = generateTypeScriptFiles(serverCode, extracted.metadata, options);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const files = {
|
|
131
|
+
"claude_desktop_config.json": hostConfigs.claudeDesktopConfig,
|
|
132
|
+
...targetFiles,
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
target,
|
|
137
|
+
serverCode,
|
|
138
|
+
hostConfig: hostConfigs.claudeDesktopConfig,
|
|
139
|
+
budget,
|
|
140
|
+
files,
|
|
141
|
+
extracted,
|
|
142
|
+
};
|
|
143
|
+
}
|