@christopher_dondici/mcp-gen 2.1.2
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/CHANGELOG.md +217 -0
- package/LICENSE +21 -0
- package/README.md +439 -0
- package/README.pt-BR.md +320 -0
- package/RELEASE_NOTES.md +98 -0
- package/SECURITY.md +75 -0
- package/SECURITY.pt-BR.md +77 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +685 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/generator.d.ts +4 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/dist/core/generator.js +275 -0
- package/dist/core/generator.js.map +1 -0
- package/dist/core/incremental.d.ts +25 -0
- package/dist/core/incremental.d.ts.map +1 -0
- package/dist/core/incremental.js +91 -0
- package/dist/core/incremental.js.map +1 -0
- package/dist/core/parser.d.ts +3 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +372 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/registry.d.ts +13 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +107 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/security-lint.d.ts +53 -0
- package/dist/core/security-lint.d.ts.map +1 -0
- package/dist/core/security-lint.js +470 -0
- package/dist/core/security-lint.js.map +1 -0
- package/dist/core/security.d.ts +41 -0
- package/dist/core/security.d.ts.map +1 -0
- package/dist/core/security.js +150 -0
- package/dist/core/security.js.map +1 -0
- package/dist/core/templating.d.ts +5 -0
- package/dist/core/templating.d.ts.map +1 -0
- package/dist/core/templating.js +211 -0
- package/dist/core/templating.js.map +1 -0
- package/dist/core/types.d.ts +104 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/go/Dockerfile.hbs +16 -0
- package/dist/templates/go/README.md.hbs +77 -0
- package/dist/templates/go/ci.yml.hbs +28 -0
- package/dist/templates/go/client.go.hbs +86 -0
- package/dist/templates/go/go.mod.hbs +5 -0
- package/dist/templates/go/models.go.hbs +28 -0
- package/dist/templates/go/server.go.hbs +220 -0
- package/dist/templates/python/Dockerfile.hbs +12 -0
- package/dist/templates/python/README.md.hbs +115 -0
- package/dist/templates/python/ci.yml.hbs +24 -0
- package/dist/templates/python/models.py.hbs +20 -0
- package/dist/templates/python/requirements.txt.hbs +3 -0
- package/dist/templates/python/server.py.hbs +195 -0
- package/dist/templates/typescript/Dockerfile.hbs +18 -0
- package/dist/templates/typescript/README.md.hbs +91 -0
- package/dist/templates/typescript/ci.yml.hbs +28 -0
- package/dist/templates/typescript/client.hbs +49 -0
- package/dist/templates/typescript/models.hbs +23 -0
- package/dist/templates/typescript/package.json.hbs +26 -0
- package/dist/templates/typescript/server.hbs +337 -0
- package/dist/templates/typescript/tsconfig.json.hbs +17 -0
- package/examples/petstore.json +130 -0
- package/examples/petstore.yaml +131 -0
- package/examples/week3.json +47 -0
- package/package.json +64 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateOutputPath = validateOutputPath;
|
|
7
|
+
exports.validatePluginPath = validatePluginPath;
|
|
8
|
+
exports.validateRemoteUrl = validateRemoteUrl;
|
|
9
|
+
exports.validateContentSize = validateContentSize;
|
|
10
|
+
exports.validateContentType = validateContentType;
|
|
11
|
+
exports.sanitizeInput = sanitizeInput;
|
|
12
|
+
exports.isPluginWhitelisted = isPluginWhitelisted;
|
|
13
|
+
exports.validatePluginModule = validatePluginModule;
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
/**
|
|
17
|
+
* Validates that a file path is within an allowed directory.
|
|
18
|
+
* Prevents path traversal attacks (e.g., ../../../etc/passwd).
|
|
19
|
+
*/
|
|
20
|
+
function validateOutputPath(filePath, baseDir) {
|
|
21
|
+
const resolvedPath = path_1.default.resolve(filePath);
|
|
22
|
+
const resolvedBase = path_1.default.resolve(baseDir);
|
|
23
|
+
if (!resolvedPath.startsWith(resolvedBase + path_1.default.sep) && resolvedPath !== resolvedBase) {
|
|
24
|
+
throw new Error(`Security error: Output path is outside the allowed directory. Path: ${filePath}, Base: ${baseDir}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validates that a plugin path exists and is a directory.
|
|
29
|
+
* Prevents loading arbitrary code from unexpected locations.
|
|
30
|
+
*/
|
|
31
|
+
function validatePluginPath(pluginPath) {
|
|
32
|
+
const resolvedPath = path_1.default.resolve(pluginPath);
|
|
33
|
+
if (!fs_1.default.existsSync(resolvedPath)) {
|
|
34
|
+
throw new Error(`Plugin path does not exist: ${pluginPath}`);
|
|
35
|
+
}
|
|
36
|
+
const stat = fs_1.default.lstatSync(resolvedPath);
|
|
37
|
+
// Reject symbolic links to prevent symlink attacks
|
|
38
|
+
if (stat.isSymbolicLink()) {
|
|
39
|
+
throw new Error(`Security error: Plugin path is a symbolic link: ${pluginPath}`);
|
|
40
|
+
}
|
|
41
|
+
if (!stat.isDirectory()) {
|
|
42
|
+
throw new Error(`Plugin path must be a directory: ${pluginPath}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validates a remote URL for fetching OpenAPI specs.
|
|
47
|
+
* Only allows HTTPS and known safe domains.
|
|
48
|
+
*/
|
|
49
|
+
function validateRemoteUrl(urlString) {
|
|
50
|
+
try {
|
|
51
|
+
const url = new URL(urlString);
|
|
52
|
+
// Only allow HTTPS (enforce encrypted transport)
|
|
53
|
+
if (url.protocol !== "https:") {
|
|
54
|
+
throw new Error("Only HTTPS URLs are allowed for remote specs");
|
|
55
|
+
}
|
|
56
|
+
// Blacklist localhost and private IPs to prevent SSRF attacks
|
|
57
|
+
let hostname = url.hostname;
|
|
58
|
+
// Handle IPv6 format - URL.hostname returns it without brackets and normalized
|
|
59
|
+
const privatePatterns = [
|
|
60
|
+
/^localhost$/i,
|
|
61
|
+
/^127\./,
|
|
62
|
+
/^192\.168\./,
|
|
63
|
+
/^10\./,
|
|
64
|
+
/^172\.(1[6-9]|2[0-9]|3[01])\./,
|
|
65
|
+
/^::1$/i,
|
|
66
|
+
/^fc00:/i,
|
|
67
|
+
/^fe80:/i,
|
|
68
|
+
/^169\.254\./,
|
|
69
|
+
];
|
|
70
|
+
for (const pattern of privatePatterns) {
|
|
71
|
+
if (pattern.test(hostname)) {
|
|
72
|
+
throw new Error(`Security error: Private or local URLs are not allowed: ${urlString}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (err instanceof Error) {
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
throw new Error(`Invalid URL: ${urlString}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validates the size of remote content to prevent DoS attacks.
|
|
85
|
+
* Max size: 50MB
|
|
86
|
+
*/
|
|
87
|
+
function validateContentSize(size, maxBytes = 50 * 1024 * 1024) {
|
|
88
|
+
if (size > maxBytes) {
|
|
89
|
+
throw new Error(`Security error: Content size (${size} bytes) exceeds maximum allowed (${maxBytes} bytes)`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Validates Content-Type of remote response.
|
|
94
|
+
* Only allows JSON and YAML for OpenAPI specs.
|
|
95
|
+
*/
|
|
96
|
+
function validateContentType(contentType) {
|
|
97
|
+
if (!contentType) {
|
|
98
|
+
throw new Error("Security error: Content-Type header is missing");
|
|
99
|
+
}
|
|
100
|
+
const validTypes = ["application/json", "application/yaml", "text/yaml", "text/plain"];
|
|
101
|
+
const baseType = contentType.split(";")[0].toLowerCase();
|
|
102
|
+
if (!validTypes.includes(baseType)) {
|
|
103
|
+
throw new Error(`Security error: Invalid Content-Type for OpenAPI spec: ${contentType}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Sanitizes user input to prevent injection attacks.
|
|
108
|
+
* Removes/escapes potentially dangerous characters.
|
|
109
|
+
*/
|
|
110
|
+
function sanitizeInput(input, maxLength = 256) {
|
|
111
|
+
if (typeof input !== "string") {
|
|
112
|
+
throw new Error("Input must be a string");
|
|
113
|
+
}
|
|
114
|
+
if (input.length > maxLength) {
|
|
115
|
+
throw new Error(`Input exceeds maximum length of ${maxLength} characters`);
|
|
116
|
+
}
|
|
117
|
+
// Remove null bytes and control characters
|
|
118
|
+
return input.replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, "");
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Creates a whitelist of allowed plugin modules.
|
|
122
|
+
* Returns true if plugin is in the whitelist.
|
|
123
|
+
*/
|
|
124
|
+
function isPluginWhitelisted(pluginName, whitelist) {
|
|
125
|
+
return whitelist.includes(pluginName);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Validates that the plugin module exports a valid structure.
|
|
129
|
+
* Prevents malicious modules from executing arbitrary code.
|
|
130
|
+
*/
|
|
131
|
+
function validatePluginModule(module) {
|
|
132
|
+
if (typeof module !== "object" || module === null) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const moduleObj = module;
|
|
136
|
+
// Only allow specific exported functions
|
|
137
|
+
const allowedExports = ["registerHandlebars"];
|
|
138
|
+
const exportedKeys = Object.keys(moduleObj);
|
|
139
|
+
for (const key of exportedKeys) {
|
|
140
|
+
if (!allowedExports.includes(key) && !key.startsWith("_")) {
|
|
141
|
+
console.warn(`Warning: Plugin exports unexpected key: ${key}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// If registerHandlebars exists, it must be a function
|
|
145
|
+
if ("registerHandlebars" in moduleObj && typeof moduleObj.registerHandlebars !== "function") {
|
|
146
|
+
throw new Error("Plugin exports invalid registerHandlebars: must be a function");
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/core/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function compileTemplate(templatePath: string): HandlebarsTemplateDelegate;
|
|
2
|
+
export declare function renderTemplate(templatePath: string, context: Record<string, unknown>): string;
|
|
3
|
+
/** Load all .hbs files in a directory as named partials */
|
|
4
|
+
export declare function registerPartials(partialsDir: string): void;
|
|
5
|
+
//# sourceMappingURL=templating.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templating.d.ts","sourceRoot":"","sources":["../../src/core/templating.ts"],"names":[],"mappings":"AAgMA,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,0BAA0B,CAQhF;AAED,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAGR;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAQ1D"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.compileTemplate = compileTemplate;
|
|
7
|
+
exports.renderTemplate = renderTemplate;
|
|
8
|
+
exports.registerPartials = registerPartials;
|
|
9
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
// Register helpers used across templates
|
|
13
|
+
handlebars_1.default.registerHelper("eq", (a, b) => a === b);
|
|
14
|
+
handlebars_1.default.registerHelper("ne", (a, b) => a !== b);
|
|
15
|
+
handlebars_1.default.registerHelper("and", (a, b) => Boolean(a && b));
|
|
16
|
+
handlebars_1.default.registerHelper("or", (a, b) => Boolean(a || b));
|
|
17
|
+
handlebars_1.default.registerHelper("not", (a) => !a);
|
|
18
|
+
handlebars_1.default.registerHelper("gt", (a, b) => a > b);
|
|
19
|
+
/** snake_case → PascalCase */
|
|
20
|
+
handlebars_1.default.registerHelper("pascal", (str) => {
|
|
21
|
+
if (typeof str !== "string")
|
|
22
|
+
return str;
|
|
23
|
+
return str
|
|
24
|
+
.split(/[_\-\s]+/)
|
|
25
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
26
|
+
.join("");
|
|
27
|
+
});
|
|
28
|
+
/** PascalCase or snake_case → camelCase */
|
|
29
|
+
handlebars_1.default.registerHelper("camel", (str) => {
|
|
30
|
+
if (typeof str !== "string")
|
|
31
|
+
return str;
|
|
32
|
+
const pascal = str
|
|
33
|
+
.split(/[_\-\s]+/)
|
|
34
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
35
|
+
.join("");
|
|
36
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
37
|
+
});
|
|
38
|
+
/** Stringify a value as JSON for example responses */
|
|
39
|
+
handlebars_1.default.registerHelper("json", (val) => JSON.stringify(val, null, 2));
|
|
40
|
+
/** Render a literal: strings get quoted+escaped, everything else is JSON. */
|
|
41
|
+
handlebars_1.default.registerHelper("literal", (val) => {
|
|
42
|
+
if (typeof val === "string") {
|
|
43
|
+
return '"' + val.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
|
|
44
|
+
}
|
|
45
|
+
return JSON.stringify(val);
|
|
46
|
+
});
|
|
47
|
+
/** Filter params by required/optional */
|
|
48
|
+
handlebars_1.default.registerHelper("requiredParams", (params) => (params ?? []).filter((p) => p.required));
|
|
49
|
+
/** Collect unique header parameters across all tools (used to render the client's buildHeaders once). */
|
|
50
|
+
handlebars_1.default.registerHelper("allHeaderParams", (tools) => {
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const tool of tools ?? []) {
|
|
54
|
+
for (const p of tool.params ?? []) {
|
|
55
|
+
if (p.in === "header" && !seen.has(p.name)) {
|
|
56
|
+
seen.add(p.name);
|
|
57
|
+
out.push({ name: p.name });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
});
|
|
63
|
+
handlebars_1.default.registerHelper("optionalParams", (params) => (params ?? []).filter((p) => !p.required));
|
|
64
|
+
/** Map MCP type to TypeScript type string */
|
|
65
|
+
handlebars_1.default.registerHelper("tsType", (type) => {
|
|
66
|
+
switch (type) {
|
|
67
|
+
case "number":
|
|
68
|
+
return "number";
|
|
69
|
+
case "boolean":
|
|
70
|
+
return "boolean";
|
|
71
|
+
case "object":
|
|
72
|
+
return "Record<string, unknown>";
|
|
73
|
+
case "array":
|
|
74
|
+
return "unknown[]";
|
|
75
|
+
default:
|
|
76
|
+
return "string";
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
/** Map MCP type to Go type string */
|
|
80
|
+
handlebars_1.default.registerHelper("goType", (type) => {
|
|
81
|
+
switch (type) {
|
|
82
|
+
case "number":
|
|
83
|
+
return "float64";
|
|
84
|
+
case "boolean":
|
|
85
|
+
return "bool";
|
|
86
|
+
case "array":
|
|
87
|
+
return "[]any";
|
|
88
|
+
case "object":
|
|
89
|
+
return "map[string]any";
|
|
90
|
+
default:
|
|
91
|
+
return "string";
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
/** Type name → Go type constructor for mcp-go's With<Type> option (String from "string", Number from "number"...). */
|
|
95
|
+
handlebars_1.default.registerHelper("pascalGoType", (type) => {
|
|
96
|
+
switch (type) {
|
|
97
|
+
case "number":
|
|
98
|
+
return "Number";
|
|
99
|
+
case "boolean":
|
|
100
|
+
return "Boolean";
|
|
101
|
+
case "object":
|
|
102
|
+
return "Object";
|
|
103
|
+
case "array":
|
|
104
|
+
return "Array";
|
|
105
|
+
default:
|
|
106
|
+
return "String";
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
/** typeof helper so Go enum literals can quote strings vs leave numbers raw. */
|
|
110
|
+
handlebars_1.default.registerHelper("typeof", (val) => typeof val);
|
|
111
|
+
/** Escape a string for a Go double-quoted string literal (\\ \n \r \t \"). */
|
|
112
|
+
handlebars_1.default.registerHelper("escapeLiteral", (val) => {
|
|
113
|
+
if (val === null || val === undefined)
|
|
114
|
+
return "";
|
|
115
|
+
const out = [];
|
|
116
|
+
for (const ch of String(val)) {
|
|
117
|
+
const code = ch.charCodeAt(0);
|
|
118
|
+
if (ch === '"')
|
|
119
|
+
out.push('\\"');
|
|
120
|
+
else if (ch === "\\")
|
|
121
|
+
out.push("\\\\");
|
|
122
|
+
else if (ch === "\n")
|
|
123
|
+
out.push("\\n");
|
|
124
|
+
else if (ch === "\r")
|
|
125
|
+
out.push("\\r");
|
|
126
|
+
else if (ch === "\t")
|
|
127
|
+
out.push("\\t");
|
|
128
|
+
else if (code < 0x20 || code === 0x7f)
|
|
129
|
+
out.push("\\u%04x".replace("%04x", code.toString(16).padStart(4, "0")));
|
|
130
|
+
else
|
|
131
|
+
out.push(ch);
|
|
132
|
+
}
|
|
133
|
+
return out.join("");
|
|
134
|
+
});
|
|
135
|
+
/** Map MCP type to Python type annotation. */
|
|
136
|
+
handlebars_1.default.registerHelper("pyType", (prop) => {
|
|
137
|
+
const base = prop.ref ?? (() => {
|
|
138
|
+
switch (prop.type) {
|
|
139
|
+
case "number": return "float";
|
|
140
|
+
case "boolean": return "bool";
|
|
141
|
+
case "object": return "dict";
|
|
142
|
+
case "array": return "List[Any]";
|
|
143
|
+
default: return "str";
|
|
144
|
+
}
|
|
145
|
+
})();
|
|
146
|
+
return prop.isArray ? `List[${base}]` : base;
|
|
147
|
+
});
|
|
148
|
+
/** Escape a string for safe embedding inside a double-quoted string literal.
|
|
149
|
+
* Escapes backslashes, double quotes, control chars and newlines so arbitrary
|
|
150
|
+
* OpenAPI descriptions cannot break or inject into generated code. */
|
|
151
|
+
handlebars_1.default.registerHelper("escapeText", (val) => {
|
|
152
|
+
if (val === null || val === undefined)
|
|
153
|
+
return "";
|
|
154
|
+
const out = [];
|
|
155
|
+
for (const ch of String(val)) {
|
|
156
|
+
const code = ch.charCodeAt(0);
|
|
157
|
+
if (ch === '"')
|
|
158
|
+
out.push('\\"');
|
|
159
|
+
else if (ch === "\\")
|
|
160
|
+
out.push("\\\\");
|
|
161
|
+
else if (ch === "\n")
|
|
162
|
+
out.push("\\n");
|
|
163
|
+
else if (ch === "\r")
|
|
164
|
+
out.push("\\r");
|
|
165
|
+
else if (ch === "\t")
|
|
166
|
+
out.push("\\t");
|
|
167
|
+
else if (code < 0x20 || code === 0x7f) {
|
|
168
|
+
out.push("\\u" + code.toString(16).padStart(4, "0"));
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
out.push(ch);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return out.join("");
|
|
175
|
+
});
|
|
176
|
+
/** Indent a block of text by N spaces */
|
|
177
|
+
handlebars_1.default.registerHelper("indent", (text, spaces) => {
|
|
178
|
+
if (typeof text !== "string")
|
|
179
|
+
return text;
|
|
180
|
+
const pad = " ".repeat(spaces);
|
|
181
|
+
return text
|
|
182
|
+
.split("\n")
|
|
183
|
+
.map((line) => (line ? pad + line : line))
|
|
184
|
+
.join("\n");
|
|
185
|
+
});
|
|
186
|
+
const templateCache = new Map();
|
|
187
|
+
function compileTemplate(templatePath) {
|
|
188
|
+
if (templateCache.has(templatePath)) {
|
|
189
|
+
return templateCache.get(templatePath);
|
|
190
|
+
}
|
|
191
|
+
const source = fs_1.default.readFileSync(templatePath, "utf-8");
|
|
192
|
+
const compiled = handlebars_1.default.compile(source, { noEscape: true });
|
|
193
|
+
templateCache.set(templatePath, compiled);
|
|
194
|
+
return compiled;
|
|
195
|
+
}
|
|
196
|
+
function renderTemplate(templatePath, context) {
|
|
197
|
+
const fn = compileTemplate(templatePath);
|
|
198
|
+
return fn(context);
|
|
199
|
+
}
|
|
200
|
+
/** Load all .hbs files in a directory as named partials */
|
|
201
|
+
function registerPartials(partialsDir) {
|
|
202
|
+
if (!fs_1.default.existsSync(partialsDir))
|
|
203
|
+
return;
|
|
204
|
+
const files = fs_1.default.readdirSync(partialsDir).filter((f) => f.endsWith(".hbs"));
|
|
205
|
+
for (const file of files) {
|
|
206
|
+
const name = path_1.default.basename(file, ".hbs");
|
|
207
|
+
const source = fs_1.default.readFileSync(path_1.default.join(partialsDir, file), "utf-8");
|
|
208
|
+
handlebars_1.default.registerPartial(name, source);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=templating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templating.js","sourceRoot":"","sources":["../../src/core/templating.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from "openapi-types";
|
|
2
|
+
export type Lang = "typescript" | "python" | "go";
|
|
3
|
+
export interface GeneratorOptions {
|
|
4
|
+
input: string;
|
|
5
|
+
lang: Lang;
|
|
6
|
+
out: string;
|
|
7
|
+
force: boolean;
|
|
8
|
+
incremental: boolean;
|
|
9
|
+
/** When true, generated handlers call the real API (HTTP) instead of returning example stubs. */
|
|
10
|
+
http: boolean;
|
|
11
|
+
/** Load an .env style file for the generated server's credentials. */
|
|
12
|
+
envFile?: string;
|
|
13
|
+
/** Paths to plugin folders or modules that can provide templates/helpers. */
|
|
14
|
+
plugins?: string[];
|
|
15
|
+
/** Optional directory to discover plugins (scanned before core templates). */
|
|
16
|
+
pluginsDir?: string;
|
|
17
|
+
serverName?: string;
|
|
18
|
+
serverVersion?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface MCPToolParam {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
24
|
+
/** Where the param lives: path | query | header | cookie | body */
|
|
25
|
+
in: "path" | "query" | "header" | "cookie" | "body";
|
|
26
|
+
required: boolean;
|
|
27
|
+
schema: OpenAPIV3.SchemaObject;
|
|
28
|
+
/** OpenAPI format hint (date-time, uuid, email, int32, ...) used for typing. */
|
|
29
|
+
format?: string;
|
|
30
|
+
/** Populated when the parameter schema is an enum. */
|
|
31
|
+
enum?: (string | number)[];
|
|
32
|
+
}
|
|
33
|
+
export interface MCPTool {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
method: string;
|
|
37
|
+
path: string;
|
|
38
|
+
params: MCPToolParam[];
|
|
39
|
+
security?: OpenAPIV3.SecurityRequirementObject[];
|
|
40
|
+
exampleResponse: unknown | null;
|
|
41
|
+
tags: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface MCPModel {
|
|
44
|
+
name: string;
|
|
45
|
+
description: string;
|
|
46
|
+
properties: MCPModelProperty[];
|
|
47
|
+
required: string[];
|
|
48
|
+
/** True when the schema is a plain enum (no object properties). */
|
|
49
|
+
isEnum: boolean;
|
|
50
|
+
enumValues?: (string | number)[];
|
|
51
|
+
oneOf?: string[];
|
|
52
|
+
anyOf?: string[];
|
|
53
|
+
discriminator?: {
|
|
54
|
+
propertyName: string;
|
|
55
|
+
mapping?: Record<string, string>;
|
|
56
|
+
} | null;
|
|
57
|
+
}
|
|
58
|
+
export interface MCPModelProperty {
|
|
59
|
+
name: string;
|
|
60
|
+
type: string;
|
|
61
|
+
description: string;
|
|
62
|
+
nullable: boolean;
|
|
63
|
+
isArray: boolean;
|
|
64
|
+
ref?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface MCPAuth {
|
|
67
|
+
baseUrl: string;
|
|
68
|
+
/** Non-empty when any operation requires security. Maps scheme name → info. */
|
|
69
|
+
schemes: Record<string, string>;
|
|
70
|
+
}
|
|
71
|
+
export interface MCPServerAST {
|
|
72
|
+
serverName: string;
|
|
73
|
+
serverVersion: string;
|
|
74
|
+
/** mcp-gen version, injected at render time by the generator. */
|
|
75
|
+
generatorVersion: string;
|
|
76
|
+
tools: MCPTool[];
|
|
77
|
+
models: MCPModel[];
|
|
78
|
+
info: {
|
|
79
|
+
title: string;
|
|
80
|
+
description: string;
|
|
81
|
+
version: string;
|
|
82
|
+
};
|
|
83
|
+
baseUrl: string;
|
|
84
|
+
/** True when any route declares security requirements. */
|
|
85
|
+
requiresAuth: boolean;
|
|
86
|
+
securitySchemes?: Record<string, OpenAPIV3.SecuritySchemeObject | OpenAPIV3.ReferenceObject>;
|
|
87
|
+
}
|
|
88
|
+
export interface GenerationResult {
|
|
89
|
+
success: boolean;
|
|
90
|
+
outputDir: string;
|
|
91
|
+
filesCreated: string[];
|
|
92
|
+
filesPreserved: string[];
|
|
93
|
+
errors: string[];
|
|
94
|
+
warnings: string[];
|
|
95
|
+
}
|
|
96
|
+
export interface ValidateResult {
|
|
97
|
+
valid: boolean;
|
|
98
|
+
tools: number;
|
|
99
|
+
models: number;
|
|
100
|
+
baseUrl: string;
|
|
101
|
+
errors: string[];
|
|
102
|
+
warnings: string[];
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { generate, validateSpec } from "./core/generator";
|
|
2
|
+
export { parseOpenAPI } from "./core/parser";
|
|
3
|
+
export { extractHandlers, injectHandlers } from "./core/incremental";
|
|
4
|
+
export { listKnownSpecs, getSpecInfo, fetchSpecToCwd, KNOWN_SPECS } from "./core/registry";
|
|
5
|
+
export { scanProject, formatReport, type SecurityRule, type SecurityReport } from "./core/security-lint";
|
|
6
|
+
export type { GeneratorOptions, GenerationResult, ValidateResult, MCPServerAST, MCPTool, MCPToolParam, MCPModel, Lang, } from "./core/types";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzG,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,IAAI,GACL,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatReport = exports.scanProject = exports.KNOWN_SPECS = exports.fetchSpecToCwd = exports.getSpecInfo = exports.listKnownSpecs = exports.injectHandlers = exports.extractHandlers = exports.parseOpenAPI = exports.validateSpec = exports.generate = void 0;
|
|
4
|
+
var generator_1 = require("./core/generator");
|
|
5
|
+
Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generator_1.generate; } });
|
|
6
|
+
Object.defineProperty(exports, "validateSpec", { enumerable: true, get: function () { return generator_1.validateSpec; } });
|
|
7
|
+
var parser_1 = require("./core/parser");
|
|
8
|
+
Object.defineProperty(exports, "parseOpenAPI", { enumerable: true, get: function () { return parser_1.parseOpenAPI; } });
|
|
9
|
+
var incremental_1 = require("./core/incremental");
|
|
10
|
+
Object.defineProperty(exports, "extractHandlers", { enumerable: true, get: function () { return incremental_1.extractHandlers; } });
|
|
11
|
+
Object.defineProperty(exports, "injectHandlers", { enumerable: true, get: function () { return incremental_1.injectHandlers; } });
|
|
12
|
+
var registry_1 = require("./core/registry");
|
|
13
|
+
Object.defineProperty(exports, "listKnownSpecs", { enumerable: true, get: function () { return registry_1.listKnownSpecs; } });
|
|
14
|
+
Object.defineProperty(exports, "getSpecInfo", { enumerable: true, get: function () { return registry_1.getSpecInfo; } });
|
|
15
|
+
Object.defineProperty(exports, "fetchSpecToCwd", { enumerable: true, get: function () { return registry_1.fetchSpecToCwd; } });
|
|
16
|
+
Object.defineProperty(exports, "KNOWN_SPECS", { enumerable: true, get: function () { return registry_1.KNOWN_SPECS; } });
|
|
17
|
+
var security_lint_1 = require("./core/security-lint");
|
|
18
|
+
Object.defineProperty(exports, "scanProject", { enumerable: true, get: function () { return security_lint_1.scanProject; } });
|
|
19
|
+
Object.defineProperty(exports, "formatReport", { enumerable: true, get: function () { return security_lint_1.formatReport; } });
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAA0D;AAAjD,qGAAA,QAAQ,OAAA;AAAE,yGAAA,YAAY,OAAA;AAC/B,wCAA6C;AAApC,sGAAA,YAAY,OAAA;AACrB,kDAAqE;AAA5D,8GAAA,eAAe,OAAA;AAAE,6GAAA,cAAc,OAAA;AACxC,4CAA2F;AAAlF,0GAAA,cAAc,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,0GAAA,cAAc,OAAA;AAAE,uGAAA,WAAW,OAAA;AACjE,sDAAyG;AAAhG,4GAAA,WAAW,OAAA;AAAE,6GAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM golang:1.22-alpine AS builder
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY go.mod ./
|
|
5
|
+
RUN go mod download
|
|
6
|
+
COPY . .
|
|
7
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -o /server .
|
|
8
|
+
|
|
9
|
+
FROM alpine:3.20 AS runtime
|
|
10
|
+
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
COPY --from=builder /server /server
|
|
13
|
+
|
|
14
|
+
ENV TOKEN=""
|
|
15
|
+
|
|
16
|
+
CMD ["/server"]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# {{info.title}} — MCP Server
|
|
2
|
+
|
|
3
|
+
> Generated by [mcp-gen](https://github.com/ChristopherDond/MCP-Generator)
|
|
4
|
+
> OpenAPI version: {{info.version}}
|
|
5
|
+
|
|
6
|
+
{{info.description}}
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
go mod tidy
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Run
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
go run .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Connect to Claude Desktop
|
|
21
|
+
|
|
22
|
+
Add to your `claude_desktop_config.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"{{serverName}}": {
|
|
28
|
+
"command": "go",
|
|
29
|
+
"args": ["run", "/absolute/path/to/main.go"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Available Tools ({{tools.length}})
|
|
36
|
+
|
|
37
|
+
{{#each tools}}
|
|
38
|
+
### `{{name}}`
|
|
39
|
+
> {{description}}
|
|
40
|
+
|
|
41
|
+
**`{{method}} {{path}}`**
|
|
42
|
+
|
|
43
|
+
{{#if params}}
|
|
44
|
+
| Name | Type | Required | Description |
|
|
45
|
+
|------|------|----------|-------------|
|
|
46
|
+
{{#each params}}
|
|
47
|
+
| `{{name}}` | `{{goType type}}` | {{#if required}}✓{{else}}—{{/if}} | {{description}} |
|
|
48
|
+
{{/each}}
|
|
49
|
+
{{/if}}
|
|
50
|
+
|
|
51
|
+
{{/each}}
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Security
|
|
56
|
+
|
|
57
|
+
### Default `authContext` Contract
|
|
58
|
+
|
|
59
|
+
The generated tools expect **scoped authorization metadata** (not raw credentials), for example:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"tokenId": "tok_abc123",
|
|
64
|
+
"principal": "user:42",
|
|
65
|
+
"expiresAt": "2026-05-11T14:00:00Z",
|
|
66
|
+
"allowedTools": ["get_orders"],
|
|
67
|
+
"endpointAllowlist": ["GET /orders"],
|
|
68
|
+
"spendLimitUsd": 5,
|
|
69
|
+
"spendUsedUsd": 1.2,
|
|
70
|
+
"revoked": false,
|
|
71
|
+
"requestId": "req_01J..."
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The scaffold blocks arguments like `token`, `authorization`, `api_key`, `client_secret` by default.
|
|
76
|
+
|
|
77
|
+
*Generated by mcp-gen — edit handlers, not the scaffold.*
|