create-glosc 0.1.0 → 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/README.md +26 -6
- package/dist/index.js +29 -3
- package/dist/templates.js +37 -23
- package/package.json +3 -2
- package/src/index.ts +30 -3
- package/src/templates.ts +40 -30
package/README.md
CHANGED
|
@@ -15,12 +15,15 @@ npm create glosc@latest <your-project-name>
|
|
|
15
15
|
```sh
|
|
16
16
|
Project name: <your-project-name>
|
|
17
17
|
Description: A brief description of your project
|
|
18
|
-
Author:
|
|
18
|
+
Author: <system-username>
|
|
19
19
|
Use Language: Python / TypeScript
|
|
20
20
|
Main File Name: main.py / index.ts
|
|
21
21
|
Readme: Y / N
|
|
22
22
|
License: MIT
|
|
23
23
|
```
|
|
24
|
+
生成的项目模板现在默认是 **MCP (Model Context Protocol) stdio server**,并内置一个最基础的工具:
|
|
25
|
+
|
|
26
|
+
- `get_current_time`:返回当前 UTC 时间(ISO 8601 字符串)
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
### Python结构
|
|
@@ -29,9 +32,9 @@ License: MIT
|
|
|
29
32
|
|
|
30
33
|
<your-project-name>/
|
|
31
34
|
├── src/ # 源代码目录
|
|
32
|
-
│ ├── main.py #
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
│ ├── main.py # MCP Server 入口 (Python, stdio)
|
|
36
|
+
├── pyproject.toml # 项目配置
|
|
37
|
+
├── requirements.txt # 依赖文件
|
|
35
38
|
├── config.yml # 配置文件
|
|
36
39
|
├── README.md # 项目说明文件
|
|
37
40
|
└── LICENSE # 许可证文件
|
|
@@ -43,13 +46,30 @@ License: MIT
|
|
|
43
46
|
```sh
|
|
44
47
|
<your-project-name>/
|
|
45
48
|
├── src/ # 源代码目录
|
|
46
|
-
│ ├── index.ts #
|
|
47
|
-
|
|
49
|
+
│ ├── index.ts # MCP Server 入口 (TypeScript, stdio)
|
|
50
|
+
├── package.json # 依赖文件(含 @modelcontextprotocol/sdk)
|
|
48
51
|
├── config.yml # 配置文件
|
|
49
52
|
├── README.md # 项目说明文件
|
|
50
53
|
└── LICENSE # 许可证文件
|
|
51
54
|
```
|
|
52
55
|
|
|
56
|
+
### 运行生成的 MCP Server
|
|
57
|
+
|
|
58
|
+
Python:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
python -m pip install -r requirements.txt
|
|
62
|
+
python src/main.py
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
TypeScript:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
npm install
|
|
69
|
+
npm run build
|
|
70
|
+
npm start
|
|
71
|
+
```
|
|
72
|
+
|
|
53
73
|
### 本地开发(维护此 CLI)
|
|
54
74
|
|
|
55
75
|
```sh
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const prompts_1 = __importDefault(require("prompts"));
|
|
40
40
|
const path = __importStar(require("node:path"));
|
|
41
|
+
const os = __importStar(require("node:os"));
|
|
41
42
|
const scaffold_1 = require("./scaffold");
|
|
42
43
|
function parseArgs(argv) {
|
|
43
44
|
const result = {
|
|
@@ -123,18 +124,42 @@ function normalizeMainFileName(language, mainFileNameRaw) {
|
|
|
123
124
|
return base;
|
|
124
125
|
return `${base}${defaultExt}`;
|
|
125
126
|
}
|
|
127
|
+
function getDefaultAuthor() {
|
|
128
|
+
const candidates = [
|
|
129
|
+
process.env.GIT_AUTHOR_NAME,
|
|
130
|
+
process.env.GIT_COMMITTER_NAME,
|
|
131
|
+
process.env.USER,
|
|
132
|
+
process.env.USERNAME,
|
|
133
|
+
process.env.LOGNAME,
|
|
134
|
+
];
|
|
135
|
+
for (const c of candidates) {
|
|
136
|
+
const v = String(c || "").trim();
|
|
137
|
+
if (v)
|
|
138
|
+
return v;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const u = os.userInfo();
|
|
142
|
+
const name = String(u?.username || "").trim();
|
|
143
|
+
if (name)
|
|
144
|
+
return name;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// ignore
|
|
148
|
+
}
|
|
149
|
+
return "Your Name";
|
|
150
|
+
}
|
|
126
151
|
async function run() {
|
|
127
152
|
const argv = process.argv.slice(2);
|
|
128
153
|
const args = parseArgs(argv);
|
|
129
154
|
if (args.defaults) {
|
|
130
155
|
if (!args.projectName) {
|
|
131
|
-
throw new Error("Project name is required (e.g. `npm create glosc
|
|
156
|
+
throw new Error("Project name is required (e.g. `npm create glosc@latest my-app -- --defaults`)");
|
|
132
157
|
}
|
|
133
158
|
const language = normalizeLanguage(args.language) || "typescript";
|
|
134
159
|
const options = {
|
|
135
160
|
projectName: String(args.projectName).trim(),
|
|
136
161
|
description: String(args.description || "A brief description of your project").trim(),
|
|
137
|
-
author: String(args.author ||
|
|
162
|
+
author: String(args.author || getDefaultAuthor()).trim(),
|
|
138
163
|
language,
|
|
139
164
|
mainFileName: normalizeMainFileName(language, args.mainFileName),
|
|
140
165
|
readme: args.readme !== undefined ? Boolean(args.readme) : true,
|
|
@@ -146,6 +171,7 @@ async function run() {
|
|
|
146
171
|
// allow `npm create ... <name>` to prefill
|
|
147
172
|
prompts_1.default.override({
|
|
148
173
|
projectName: args.projectName,
|
|
174
|
+
author: args.author,
|
|
149
175
|
});
|
|
150
176
|
let selectedLanguage;
|
|
151
177
|
const response = await (0, prompts_1.default)([
|
|
@@ -172,7 +198,7 @@ async function run() {
|
|
|
172
198
|
type: "text",
|
|
173
199
|
name: "author",
|
|
174
200
|
message: "Author:",
|
|
175
|
-
initial:
|
|
201
|
+
initial: getDefaultAuthor(),
|
|
176
202
|
},
|
|
177
203
|
{
|
|
178
204
|
type: "select",
|
package/dist/templates.js
CHANGED
|
@@ -14,7 +14,11 @@ function mitLicenseText({ author }) {
|
|
|
14
14
|
function projectReadme(options) {
|
|
15
15
|
const { projectName, description, author, language, mainFileName } = options;
|
|
16
16
|
const langLabel = language === "python" ? "Python" : "TypeScript";
|
|
17
|
-
|
|
17
|
+
const entry = `src/${mainFileName}`;
|
|
18
|
+
const runSection = language === "python"
|
|
19
|
+
? `## Run (Python)\n\n\n\n1) Install deps\n\n\n\n\`\`\`sh\npython -m pip install -r requirements.txt\n\`\`\`\n\n\n\n2) Run the MCP server (stdio)\n\n\n\n\`\`\`sh\npython ${entry}\n\`\`\`\n\n\n\nThis server speaks MCP over stdio. Connect using an MCP client (e.g. an editor integration).\n`
|
|
20
|
+
: `## Run (TypeScript)\n\n\n\n1) Install deps\n\n\n\n\`\`\`sh\nnpm install\n\`\`\`\n\n\n\n2) Build\n\n\n\n\`\`\`sh\nnpm run build\n\`\`\`\n\n\n\n3) Run the MCP server (stdio)\n\n\n\n\`\`\`sh\nnpm start\n\`\`\`\n\n\n\nThis server speaks MCP over stdio. Connect using an MCP client (e.g. an editor integration).\n`;
|
|
21
|
+
return `# ${projectName}\n\n${description || ""}\n\n## Author\n\n${author || ""}\n\n## Language\n\n${langLabel}\n\n## Entry\n\n- ${entry}\n\n## MCP Tools\n\n- get_current_time: Returns the current time (UTC, ISO 8601)\n\n${runSection}\n\n## Config\n\n- config.yml\n`;
|
|
18
22
|
}
|
|
19
23
|
function configYml(options) {
|
|
20
24
|
const { projectName, description, author, language, mainFileName } = options;
|
|
@@ -27,36 +31,43 @@ function configYml(options) {
|
|
|
27
31
|
"",
|
|
28
32
|
].join("\n");
|
|
29
33
|
}
|
|
30
|
-
function pythonMain({ projectName,
|
|
31
|
-
const safeName = String(projectName).replace(/"/g, '\\"');
|
|
32
|
-
|
|
33
|
-
return `def main():\n print("${safeName}")\n ${description ? `print("${safeDesc}")` : "pass"}\n\n\nif __name__ == "__main__":\n main()\n`;
|
|
34
|
+
function pythonMain({ projectName, }) {
|
|
35
|
+
const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
|
|
36
|
+
return `from datetime import datetime, timezone\n\nfrom mcp.server.fastmcp import FastMCP\n\n# Minimal MCP server (stdio)\n\nmcp = FastMCP("${safeName}")\n\n\n@mcp.tool()\nasync def get_current_time() -> str:\n """Return the current time in UTC (ISO 8601)."""\n\n return datetime.now(timezone.utc).isoformat()\n\n\ndef main():\n mcp.run(transport="stdio")\n\n\nif __name__ == "__main__":\n main()\n`;
|
|
34
37
|
}
|
|
35
38
|
function pythonRequirements() {
|
|
36
|
-
return
|
|
39
|
+
return `mcp\n`;
|
|
37
40
|
}
|
|
38
41
|
function pythonPyproject({ projectName, author, }) {
|
|
39
42
|
const safeName = String(projectName || "glosc-project")
|
|
40
43
|
.trim()
|
|
41
44
|
.replace(/\s+/g, "-");
|
|
42
45
|
const safeAuthor = String(author || "").replace(/"/g, '\\"');
|
|
43
|
-
|
|
46
|
+
const authorsLine = safeAuthor.trim()
|
|
47
|
+
? `authors = [{ name = "${safeAuthor}" }]\n`
|
|
48
|
+
: "";
|
|
49
|
+
return `# Minimal pyproject.toml (adjust as needed)\n\n[project]\nname = "${safeName}"\nversion = "0.1.0"\ndescription = ""\n${authorsLine}requires-python = ">=3.10"\ndependencies = [\n "mcp",\n]\n\n[build-system]\nrequires = ["setuptools>=61.0"]\nbuild-backend = "setuptools.build_meta"\n`;
|
|
44
50
|
}
|
|
45
51
|
function nodePackageJson(options) {
|
|
46
52
|
const { projectName, description, author, mainFileName } = options;
|
|
47
|
-
const
|
|
53
|
+
const distEntry = `dist/${mainFileName.replace(/\.ts$/i, ".js")}`;
|
|
48
54
|
const pkg = {
|
|
49
55
|
name: projectName,
|
|
50
56
|
version: "0.1.0",
|
|
51
57
|
description: description || "",
|
|
52
58
|
author: author || "",
|
|
53
59
|
private: true,
|
|
60
|
+
type: "module",
|
|
54
61
|
scripts: {
|
|
55
62
|
build: "tsc -p .",
|
|
56
|
-
start: `node ${
|
|
63
|
+
start: `node ${distEntry}`,
|
|
64
|
+
},
|
|
65
|
+
dependencies: {
|
|
66
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
57
67
|
},
|
|
58
68
|
devDependencies: {
|
|
59
|
-
typescript: "^5.
|
|
69
|
+
typescript: "^5.9.3",
|
|
70
|
+
"@types/node": "^22.19.2",
|
|
60
71
|
},
|
|
61
72
|
};
|
|
62
73
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
@@ -64,20 +75,23 @@ function nodePackageJson(options) {
|
|
|
64
75
|
function tsConfig() {
|
|
65
76
|
return (JSON.stringify({
|
|
66
77
|
compilerOptions: {
|
|
67
|
-
target: "
|
|
68
|
-
module: "
|
|
78
|
+
target: "ES2022",
|
|
79
|
+
module: "Node16",
|
|
69
80
|
strict: true,
|
|
70
|
-
outDir: "
|
|
71
|
-
rootDir: "
|
|
81
|
+
outDir: "dist",
|
|
82
|
+
rootDir: "src",
|
|
72
83
|
esModuleInterop: true,
|
|
84
|
+
moduleResolution: "Node16",
|
|
85
|
+
types: ["node"],
|
|
86
|
+
skipLibCheck: true,
|
|
87
|
+
forceConsistentCasingInFileNames: true,
|
|
73
88
|
},
|
|
74
|
-
include: ["
|
|
89
|
+
include: ["src/**/*.ts"],
|
|
75
90
|
}, null, 2) + "\n");
|
|
76
91
|
}
|
|
77
|
-
function tsMain({ projectName
|
|
78
|
-
const safeName = String(projectName).replace(
|
|
79
|
-
|
|
80
|
-
return `console.log("${safeName}");\n${description ? `console.log("${safeDesc}");\n` : ""}`;
|
|
92
|
+
function tsMain({ projectName }) {
|
|
93
|
+
const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
|
|
94
|
+
return `import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";\nimport { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";\n\nconst server = new McpServer({\n name: "${safeName}",\n version: "0.1.0",\n});\n\nserver.registerTool(\n "get_current_time",\n {\n title: "Get Current Time",\n description: "Return the current time in UTC (ISO 8601)",\n inputSchema: {},\n },\n async () => {\n return {\n content: [\n {\n type: "text",\n text: new Date().toISOString(),\n },\n ],\n };\n },\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error("MCP Server running on stdio");\n}\n\nmain().catch((error) => {\n console.error("Fatal error in main():", error);\n process.exit(1);\n});\n`;
|
|
81
95
|
}
|
|
82
96
|
function getProjectFiles(options) {
|
|
83
97
|
const files = [];
|
|
@@ -100,11 +114,11 @@ function getProjectFiles(options) {
|
|
|
100
114
|
content: pythonMain(options),
|
|
101
115
|
});
|
|
102
116
|
files.push({
|
|
103
|
-
relativePath: "
|
|
117
|
+
relativePath: "requirements.txt",
|
|
104
118
|
content: pythonRequirements(),
|
|
105
119
|
});
|
|
106
120
|
files.push({
|
|
107
|
-
relativePath: "
|
|
121
|
+
relativePath: "pyproject.toml",
|
|
108
122
|
content: pythonPyproject(options),
|
|
109
123
|
});
|
|
110
124
|
}
|
|
@@ -114,10 +128,10 @@ function getProjectFiles(options) {
|
|
|
114
128
|
content: tsMain(options),
|
|
115
129
|
});
|
|
116
130
|
files.push({
|
|
117
|
-
relativePath: "
|
|
131
|
+
relativePath: "package.json",
|
|
118
132
|
content: nodePackageJson(options),
|
|
119
133
|
});
|
|
120
|
-
files.push({ relativePath: "
|
|
134
|
+
files.push({ relativePath: "tsconfig.json", content: tsConfig() });
|
|
121
135
|
}
|
|
122
136
|
return files;
|
|
123
137
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-glosc",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Scaffold Glosc projects (Python/TypeScript
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Scaffold Glosc projects (Python/TypeScript) via npm create",
|
|
5
5
|
"author": "glosc-ai",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
8
|
+
"create-glosc": "bin/index.js",
|
|
8
9
|
"glosc": "bin/index.js"
|
|
9
10
|
},
|
|
10
11
|
"type": "commonjs",
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import prompts from "prompts";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
3
4
|
import { scaffoldProject } from "./scaffold";
|
|
4
5
|
|
|
5
6
|
type Language = "python" | "typescript";
|
|
@@ -128,6 +129,31 @@ function normalizeMainFileName(
|
|
|
128
129
|
return `${base}${defaultExt}`;
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
function getDefaultAuthor(): string {
|
|
133
|
+
const candidates = [
|
|
134
|
+
process.env.GIT_AUTHOR_NAME,
|
|
135
|
+
process.env.GIT_COMMITTER_NAME,
|
|
136
|
+
process.env.USER,
|
|
137
|
+
process.env.USERNAME,
|
|
138
|
+
process.env.LOGNAME,
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
for (const c of candidates) {
|
|
142
|
+
const v = String(c || "").trim();
|
|
143
|
+
if (v) return v;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const u = os.userInfo();
|
|
148
|
+
const name = String(u?.username || "").trim();
|
|
149
|
+
if (name) return name;
|
|
150
|
+
} catch {
|
|
151
|
+
// ignore
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return "Your Name";
|
|
155
|
+
}
|
|
156
|
+
|
|
131
157
|
async function run(): Promise<void> {
|
|
132
158
|
const argv = process.argv.slice(2);
|
|
133
159
|
const args = parseArgs(argv);
|
|
@@ -135,7 +161,7 @@ async function run(): Promise<void> {
|
|
|
135
161
|
if (args.defaults) {
|
|
136
162
|
if (!args.projectName) {
|
|
137
163
|
throw new Error(
|
|
138
|
-
"Project name is required (e.g. `npm create glosc
|
|
164
|
+
"Project name is required (e.g. `npm create glosc@latest my-app -- --defaults`)"
|
|
139
165
|
);
|
|
140
166
|
}
|
|
141
167
|
|
|
@@ -146,7 +172,7 @@ async function run(): Promise<void> {
|
|
|
146
172
|
description: String(
|
|
147
173
|
args.description || "A brief description of your project"
|
|
148
174
|
).trim(),
|
|
149
|
-
author: String(args.author ||
|
|
175
|
+
author: String(args.author || getDefaultAuthor()).trim(),
|
|
150
176
|
language,
|
|
151
177
|
mainFileName: normalizeMainFileName(language, args.mainFileName),
|
|
152
178
|
readme: args.readme !== undefined ? Boolean(args.readme) : true,
|
|
@@ -160,6 +186,7 @@ async function run(): Promise<void> {
|
|
|
160
186
|
// allow `npm create ... <name>` to prefill
|
|
161
187
|
prompts.override({
|
|
162
188
|
projectName: args.projectName,
|
|
189
|
+
author: args.author,
|
|
163
190
|
});
|
|
164
191
|
|
|
165
192
|
let selectedLanguage: Language | undefined;
|
|
@@ -188,7 +215,7 @@ async function run(): Promise<void> {
|
|
|
188
215
|
type: "text",
|
|
189
216
|
name: "author",
|
|
190
217
|
message: "Author:",
|
|
191
|
-
initial:
|
|
218
|
+
initial: getDefaultAuthor(),
|
|
192
219
|
},
|
|
193
220
|
{
|
|
194
221
|
type: "select",
|
package/src/templates.ts
CHANGED
|
@@ -32,9 +32,15 @@ function projectReadme(options: ProjectOptions): string {
|
|
|
32
32
|
options;
|
|
33
33
|
const langLabel = language === "python" ? "Python" : "TypeScript";
|
|
34
34
|
|
|
35
|
+
const entry = `src/${mainFileName}`;
|
|
36
|
+
const runSection =
|
|
37
|
+
language === "python"
|
|
38
|
+
? `## Run (Python)\n\n\n\n1) Install deps\n\n\n\n\`\`\`sh\npython -m pip install -r requirements.txt\n\`\`\`\n\n\n\n2) Run the MCP server (stdio)\n\n\n\n\`\`\`sh\npython ${entry}\n\`\`\`\n\n\n\nThis server speaks MCP over stdio. Connect using an MCP client (e.g. an editor integration).\n`
|
|
39
|
+
: `## Run (TypeScript)\n\n\n\n1) Install deps\n\n\n\n\`\`\`sh\nnpm install\n\`\`\`\n\n\n\n2) Build\n\n\n\n\`\`\`sh\nnpm run build\n\`\`\`\n\n\n\n3) Run the MCP server (stdio)\n\n\n\n\`\`\`sh\nnpm start\n\`\`\`\n\n\n\nThis server speaks MCP over stdio. Connect using an MCP client (e.g. an editor integration).\n`;
|
|
40
|
+
|
|
35
41
|
return `# ${projectName}\n\n${description || ""}\n\n## Author\n\n${
|
|
36
42
|
author || ""
|
|
37
|
-
}\n\n## Language\n\n${langLabel}\n\n## Entry\n\n-
|
|
43
|
+
}\n\n## Language\n\n${langLabel}\n\n## Entry\n\n- ${entry}\n\n## MCP Tools\n\n- get_current_time: Returns the current time (UTC, ISO 8601)\n\n${runSection}\n\n## Config\n\n- config.yml\n`;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
function configYml(options: ProjectOptions): string {
|
|
@@ -52,18 +58,14 @@ function configYml(options: ProjectOptions): string {
|
|
|
52
58
|
|
|
53
59
|
function pythonMain({
|
|
54
60
|
projectName,
|
|
55
|
-
description,
|
|
56
61
|
}: Pick<ProjectOptions, "projectName" | "description">): string {
|
|
57
|
-
const safeName = String(projectName).replace(/"/g, '\\"');
|
|
58
|
-
const safeDesc = String(description || "").replace(/"/g, '\\"');
|
|
62
|
+
const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
|
|
59
63
|
|
|
60
|
-
return `
|
|
61
|
-
description ? `print("${safeDesc}")` : "pass"
|
|
62
|
-
}\n\n\nif __name__ == "__main__":\n main()\n`;
|
|
64
|
+
return `from datetime import datetime, timezone\n\nfrom mcp.server.fastmcp import FastMCP\n\n# Minimal MCP server (stdio)\n\nmcp = FastMCP("${safeName}")\n\n\n@mcp.tool()\nasync def get_current_time() -> str:\n """Return the current time in UTC (ISO 8601)."""\n\n return datetime.now(timezone.utc).isoformat()\n\n\ndef main():\n mcp.run(transport="stdio")\n\n\nif __name__ == "__main__":\n main()\n`;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
function pythonRequirements(): string {
|
|
66
|
-
return
|
|
68
|
+
return `mcp\n`;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
function pythonPyproject({
|
|
@@ -76,12 +78,16 @@ function pythonPyproject({
|
|
|
76
78
|
|
|
77
79
|
const safeAuthor = String(author || "").replace(/"/g, '\\"');
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
const authorsLine = safeAuthor.trim()
|
|
82
|
+
? `authors = [{ name = "${safeAuthor}" }]\n`
|
|
83
|
+
: "";
|
|
84
|
+
|
|
85
|
+
return `# Minimal pyproject.toml (adjust as needed)\n\n[project]\nname = "${safeName}"\nversion = "0.1.0"\ndescription = ""\n${authorsLine}requires-python = ">=3.10"\ndependencies = [\n "mcp",\n]\n\n[build-system]\nrequires = ["setuptools>=61.0"]\nbuild-backend = "setuptools.build_meta"\n`;
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
function nodePackageJson(options: ProjectOptions): string {
|
|
83
89
|
const { projectName, description, author, mainFileName } = options;
|
|
84
|
-
const
|
|
90
|
+
const distEntry = `dist/${mainFileName.replace(/\.ts$/i, ".js")}`;
|
|
85
91
|
|
|
86
92
|
const pkg: Record<string, unknown> = {
|
|
87
93
|
name: projectName,
|
|
@@ -89,12 +95,17 @@ function nodePackageJson(options: ProjectOptions): string {
|
|
|
89
95
|
description: description || "",
|
|
90
96
|
author: author || "",
|
|
91
97
|
private: true,
|
|
98
|
+
type: "module",
|
|
92
99
|
scripts: {
|
|
93
100
|
build: "tsc -p .",
|
|
94
|
-
start: `node ${
|
|
101
|
+
start: `node ${distEntry}`,
|
|
102
|
+
},
|
|
103
|
+
dependencies: {
|
|
104
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
95
105
|
},
|
|
96
106
|
devDependencies: {
|
|
97
|
-
typescript: "^5.
|
|
107
|
+
typescript: "^5.9.3",
|
|
108
|
+
"@types/node": "^22.19.2",
|
|
98
109
|
},
|
|
99
110
|
};
|
|
100
111
|
|
|
@@ -106,14 +117,18 @@ function tsConfig(): string {
|
|
|
106
117
|
JSON.stringify(
|
|
107
118
|
{
|
|
108
119
|
compilerOptions: {
|
|
109
|
-
target: "
|
|
110
|
-
module: "
|
|
120
|
+
target: "ES2022",
|
|
121
|
+
module: "Node16",
|
|
111
122
|
strict: true,
|
|
112
|
-
outDir: "
|
|
113
|
-
rootDir: "
|
|
123
|
+
outDir: "dist",
|
|
124
|
+
rootDir: "src",
|
|
114
125
|
esModuleInterop: true,
|
|
126
|
+
moduleResolution: "Node16",
|
|
127
|
+
types: ["node"],
|
|
128
|
+
skipLibCheck: true,
|
|
129
|
+
forceConsistentCasingInFileNames: true,
|
|
115
130
|
},
|
|
116
|
-
include: ["
|
|
131
|
+
include: ["src/**/*.ts"],
|
|
117
132
|
},
|
|
118
133
|
null,
|
|
119
134
|
2
|
|
@@ -121,15 +136,10 @@ function tsConfig(): string {
|
|
|
121
136
|
);
|
|
122
137
|
}
|
|
123
138
|
|
|
124
|
-
function tsMain({
|
|
125
|
-
projectName,
|
|
126
|
-
|
|
127
|
-
}:
|
|
128
|
-
const safeName = String(projectName).replace(/`/g, "\\`");
|
|
129
|
-
const safeDesc = String(description || "").replace(/`/g, "\\`");
|
|
130
|
-
return `console.log("${safeName}");\n${
|
|
131
|
-
description ? `console.log("${safeDesc}");\n` : ""
|
|
132
|
-
}`;
|
|
139
|
+
function tsMain({ projectName }: Pick<ProjectOptions, "projectName">): string {
|
|
140
|
+
const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
|
|
141
|
+
|
|
142
|
+
return `import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";\nimport { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";\n\nconst server = new McpServer({\n name: "${safeName}",\n version: "0.1.0",\n});\n\nserver.registerTool(\n "get_current_time",\n {\n title: "Get Current Time",\n description: "Return the current time in UTC (ISO 8601)",\n inputSchema: {},\n },\n async () => {\n return {\n content: [\n {\n type: "text",\n text: new Date().toISOString(),\n },\n ],\n };\n },\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error("MCP Server running on stdio");\n}\n\nmain().catch((error) => {\n console.error("Fatal error in main():", error);\n process.exit(1);\n});\n`;
|
|
133
143
|
}
|
|
134
144
|
|
|
135
145
|
export function getProjectFiles(options: ProjectOptions): ProjectFile[] {
|
|
@@ -157,11 +167,11 @@ export function getProjectFiles(options: ProjectOptions): ProjectFile[] {
|
|
|
157
167
|
content: pythonMain(options),
|
|
158
168
|
});
|
|
159
169
|
files.push({
|
|
160
|
-
relativePath: "
|
|
170
|
+
relativePath: "requirements.txt",
|
|
161
171
|
content: pythonRequirements(),
|
|
162
172
|
});
|
|
163
173
|
files.push({
|
|
164
|
-
relativePath: "
|
|
174
|
+
relativePath: "pyproject.toml",
|
|
165
175
|
content: pythonPyproject(options),
|
|
166
176
|
});
|
|
167
177
|
}
|
|
@@ -172,10 +182,10 @@ export function getProjectFiles(options: ProjectOptions): ProjectFile[] {
|
|
|
172
182
|
content: tsMain(options),
|
|
173
183
|
});
|
|
174
184
|
files.push({
|
|
175
|
-
relativePath: "
|
|
185
|
+
relativePath: "package.json",
|
|
176
186
|
content: nodePackageJson(options),
|
|
177
187
|
});
|
|
178
|
-
files.push({ relativePath: "
|
|
188
|
+
files.push({ relativePath: "tsconfig.json", content: tsConfig() });
|
|
179
189
|
}
|
|
180
190
|
|
|
181
191
|
return files;
|