create-glosc 0.1.1 → 0.2.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 CHANGED
@@ -15,7 +15,7 @@ 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: Your Name
18
+ Author: <system-username>
19
19
  Use Language: Python / TypeScript
20
20
  Main File Name: main.py / index.ts
21
21
  Readme: Y / N
@@ -31,8 +31,7 @@ License: MIT
31
31
  ```sh
32
32
 
33
33
  <your-project-name>/
34
- ├── src/ # 源代码目录
35
- │ ├── main.py # MCP Server 入口 (Python, stdio)
34
+ ├── main.py # MCP Server 入口 (Python, stdio)
36
35
  ├── pyproject.toml # 项目配置
37
36
  ├── requirements.txt # 依赖文件
38
37
  ├── config.yml # 配置文件
@@ -59,7 +58,7 @@ Python:
59
58
 
60
59
  ```sh
61
60
  python -m pip install -r requirements.txt
62
- python src/main.py
61
+ python main.py
63
62
  ```
64
63
 
65
64
  TypeScript:
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,6 +124,30 @@ 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);
@@ -134,7 +159,7 @@ async function run() {
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 || "Your Name").trim(),
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: "Your Name",
201
+ initial: getDefaultAuthor(),
176
202
  },
177
203
  {
178
204
  type: "select",
package/dist/templates.js CHANGED
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getProjectFiles = getProjectFiles;
4
+ function entryPath(options) {
5
+ return options.language === "python"
6
+ ? options.mainFileName
7
+ : `src/${options.mainFileName}`;
8
+ }
4
9
  function escapeYamlString(value) {
5
10
  const s = String(value ?? "");
6
11
  const escaped = s.replace(/"/g, '\\"');
@@ -14,7 +19,7 @@ function mitLicenseText({ author }) {
14
19
  function projectReadme(options) {
15
20
  const { projectName, description, author, language, mainFileName } = options;
16
21
  const langLabel = language === "python" ? "Python" : "TypeScript";
17
- const entry = `src/${mainFileName}`;
22
+ const entry = entryPath(options);
18
23
  const runSection = language === "python"
19
24
  ? `## 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
25
  : `## 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`;
@@ -27,7 +32,7 @@ function configYml(options) {
27
32
  `description: ${escapeYamlString(description)}`,
28
33
  `author: ${escapeYamlString(author)}`,
29
34
  `language: ${escapeYamlString(language)}`,
30
- `entry: ${escapeYamlString(`src/${mainFileName}`)}`,
35
+ `entry: ${escapeYamlString(entryPath(options))}`,
31
36
  "",
32
37
  ].join("\n");
33
38
  }
@@ -89,7 +94,7 @@ function tsConfig() {
89
94
  include: ["src/**/*.ts"],
90
95
  }, null, 2) + "\n");
91
96
  }
92
- function tsMain({ projectName, }) {
97
+ function tsMain({ projectName }) {
93
98
  const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
94
99
  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`;
95
100
  }
@@ -110,7 +115,7 @@ function getProjectFiles(options) {
110
115
  }
111
116
  if (options.language === "python") {
112
117
  files.push({
113
- relativePath: `src/${options.mainFileName}`,
118
+ relativePath: options.mainFileName,
114
119
  content: pythonMain(options),
115
120
  });
116
121
  files.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-glosc",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Scaffold Glosc projects (Python/TypeScript) via npm create",
5
5
  "author": "glosc-ai",
6
6
  "license": "MIT",
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);
@@ -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 || "Your Name").trim(),
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: "Your Name",
218
+ initial: getDefaultAuthor(),
192
219
  },
193
220
  {
194
221
  type: "select",
package/src/templates.ts CHANGED
@@ -15,6 +15,12 @@ export type ProjectFile = {
15
15
  content: string;
16
16
  };
17
17
 
18
+ function entryPath(options: ProjectOptions): string {
19
+ return options.language === "python"
20
+ ? options.mainFileName
21
+ : `src/${options.mainFileName}`;
22
+ }
23
+
18
24
  function escapeYamlString(value: unknown): string {
19
25
  const s = String(value ?? "");
20
26
  const escaped = s.replace(/"/g, '\\"');
@@ -32,7 +38,7 @@ function projectReadme(options: ProjectOptions): string {
32
38
  options;
33
39
  const langLabel = language === "python" ? "Python" : "TypeScript";
34
40
 
35
- const entry = `src/${mainFileName}`;
41
+ const entry = entryPath(options);
36
42
  const runSection =
37
43
  language === "python"
38
44
  ? `## 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`
@@ -51,7 +57,7 @@ function configYml(options: ProjectOptions): string {
51
57
  `description: ${escapeYamlString(description)}`,
52
58
  `author: ${escapeYamlString(author)}`,
53
59
  `language: ${escapeYamlString(language)}`,
54
- `entry: ${escapeYamlString(`src/${mainFileName}`)}`,
60
+ `entry: ${escapeYamlString(entryPath(options))}`,
55
61
  "",
56
62
  ].join("\n");
57
63
  }
@@ -136,9 +142,7 @@ function tsConfig(): string {
136
142
  );
137
143
  }
138
144
 
139
- function tsMain({
140
- projectName,
141
- }: Pick<ProjectOptions, "projectName">): string {
145
+ function tsMain({ projectName }: Pick<ProjectOptions, "projectName">): string {
142
146
  const safeName = String(projectName || "mcp-server").replace(/"/g, '\\"');
143
147
 
144
148
  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`;
@@ -165,7 +169,7 @@ export function getProjectFiles(options: ProjectOptions): ProjectFile[] {
165
169
 
166
170
  if (options.language === "python") {
167
171
  files.push({
168
- relativePath: `src/${options.mainFileName}`,
172
+ relativePath: options.mainFileName,
169
173
  content: pythonMain(options),
170
174
  });
171
175
  files.push({