@lambertkeith/spec-go 0.2.5 → 0.3.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.
@@ -0,0 +1,591 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/mcp/server.ts
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+
7
+ // src/mcp/tools.ts
8
+ import { z } from "zod";
9
+ import path5 from "path";
10
+
11
+ // src/core/config.ts
12
+ import fs from "fs";
13
+ import path from "path";
14
+ import os from "os";
15
+ var CONFIG_PATH = path.join(os.homedir(), ".spec-go.json");
16
+ function loadConfig() {
17
+ try {
18
+ if (fs.existsSync(CONFIG_PATH)) {
19
+ const content = fs.readFileSync(CONFIG_PATH, "utf-8");
20
+ return JSON.parse(content);
21
+ }
22
+ } catch {
23
+ }
24
+ return {};
25
+ }
26
+
27
+ // src/core/debug.ts
28
+ var debugEnabled = false;
29
+ function debug(category, message, data) {
30
+ if (!debugEnabled) return;
31
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
32
+ const prefix = `[DEBUG ${timestamp}] [${category}]`;
33
+ if (data !== void 0) {
34
+ const dataStr = formatData(data);
35
+ console.error(`${prefix} ${message}`, dataStr);
36
+ } else {
37
+ console.error(`${prefix} ${message}`);
38
+ }
39
+ }
40
+ function formatData(data) {
41
+ try {
42
+ const str = JSON.stringify(data, null, 2);
43
+ if (str.length > 500) {
44
+ return str.slice(0, 500) + "...(truncated)";
45
+ }
46
+ return str;
47
+ } catch {
48
+ return String(data);
49
+ }
50
+ }
51
+
52
+ // src/core/utils.ts
53
+ import path2 from "path";
54
+ import { fileURLToPath } from "url";
55
+ import { spawn } from "child_process";
56
+ var __filename = fileURLToPath(import.meta.url);
57
+ var __dirname = path2.dirname(__filename);
58
+ function getTemplatesDir() {
59
+ return path2.resolve(__dirname, "..", "..", "templates");
60
+ }
61
+ function isValidPackageName(name) {
62
+ return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name);
63
+ }
64
+ function toValidPackageName(name) {
65
+ return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
66
+ }
67
+ function execAsync(command, args, options = {}) {
68
+ debug("exec", `\u6267\u884C\u547D\u4EE4: ${command} ${args.join(" ")}`, { cwd: options.cwd });
69
+ return new Promise((resolve) => {
70
+ const proc = spawn(command, args, {
71
+ cwd: options.cwd,
72
+ stdio: options.stdio === "inherit" ? "inherit" : "pipe",
73
+ shell: true
74
+ });
75
+ let stdout = "";
76
+ let stderr = "";
77
+ if (proc.stdout) {
78
+ proc.stdout.on("data", (data) => {
79
+ stdout += data.toString();
80
+ });
81
+ }
82
+ if (proc.stderr) {
83
+ proc.stderr.on("data", (data) => {
84
+ stderr += data.toString();
85
+ });
86
+ }
87
+ proc.on("close", (code) => {
88
+ debug("exec", `\u547D\u4EE4\u5B8C\u6210\uFF0C\u9000\u51FA\u7801: ${code ?? 1}`);
89
+ resolve({ code: code ?? 1, stdout, stderr });
90
+ });
91
+ proc.on("error", (err) => {
92
+ debug("exec", `\u547D\u4EE4\u9519\u8BEF: ${err.message}`);
93
+ resolve({ code: 1, stdout, stderr });
94
+ });
95
+ });
96
+ }
97
+
98
+ // src/core/scaffold.ts
99
+ import path3 from "path";
100
+ import fs2 from "fs-extra";
101
+ async function scaffoldProject(options) {
102
+ const templatesDir = getTemplatesDir();
103
+ const registryPath = path3.join(templatesDir, "template.config.json");
104
+ const registry = await fs2.readJson(registryPath);
105
+ debug("scaffold", `\u5F00\u59CB\u811A\u624B\u67B6\u9879\u76EE: ${options.projectName}`);
106
+ debug("scaffold", `\u6A21\u677F: ${options.template}`);
107
+ debug("scaffold", `\u76EE\u6807\u76EE\u5F55: ${options.targetDir}`);
108
+ const templateEntry = registry.templates.find((t) => t.name === options.template);
109
+ if (!templateEntry) {
110
+ throw new Error(`\u672A\u627E\u5230\u6A21\u677F: ${options.template}`);
111
+ }
112
+ const templateDir = path3.join(templatesDir, templateEntry.dir);
113
+ const templateConfigPath = path3.join(templateDir, "_template.json");
114
+ debug("scaffold", `\u6A21\u677F\u76EE\u5F55: ${templateDir}`);
115
+ let templateConfig = null;
116
+ if (await fs2.pathExists(templateConfigPath)) {
117
+ templateConfig = await fs2.readJson(templateConfigPath);
118
+ debug("scaffold", "\u6A21\u677F\u914D\u7F6E", templateConfig);
119
+ }
120
+ await fs2.ensureDir(options.targetDir);
121
+ const files = await fs2.readdir(templateDir);
122
+ debug("scaffold", `\u6A21\u677F\u6587\u4EF6\u6570\u91CF: ${files.length}`);
123
+ for (const file of files) {
124
+ if (file === "_template.json") {
125
+ continue;
126
+ }
127
+ const srcPath = path3.join(templateDir, file);
128
+ let destFileName = file;
129
+ if (templateConfig?.fileRenames?.[file]) {
130
+ destFileName = templateConfig.fileRenames[file];
131
+ if (destFileName === "{{projectName}}") {
132
+ destFileName = options.projectName;
133
+ }
134
+ }
135
+ const destPath = path3.join(options.targetDir, destFileName);
136
+ const stat = await fs2.stat(srcPath);
137
+ debug("scaffold", `\u590D\u5236: ${file} -> ${destFileName}`);
138
+ if (stat.isDirectory()) {
139
+ await copyDirectory(srcPath, destPath, options.projectName, templateConfig);
140
+ } else {
141
+ await copyFile(srcPath, destPath, options.projectName, templateConfig);
142
+ }
143
+ }
144
+ debug("scaffold", "\u811A\u624B\u67B6\u5B8C\u6210");
145
+ return templateConfig;
146
+ }
147
+ async function copyDirectory(srcDir, destDir, projectName, config) {
148
+ await fs2.ensureDir(destDir);
149
+ const files = await fs2.readdir(srcDir);
150
+ for (const file of files) {
151
+ const srcPath = path3.join(srcDir, file);
152
+ let destFileName = file;
153
+ if (config?.fileRenames?.[file]) {
154
+ destFileName = config.fileRenames[file];
155
+ if (destFileName === "{{projectName}}") {
156
+ destFileName = projectName;
157
+ }
158
+ }
159
+ const destPath = path3.join(destDir, destFileName);
160
+ const stat = await fs2.stat(srcPath);
161
+ if (stat.isDirectory()) {
162
+ await copyDirectory(srcPath, destPath, projectName, config);
163
+ } else {
164
+ await copyFile(srcPath, destPath, projectName, config);
165
+ }
166
+ }
167
+ }
168
+ async function copyFile(srcPath, destPath, projectName, config) {
169
+ const binaryExtensions = [
170
+ ".png",
171
+ ".jpg",
172
+ ".jpeg",
173
+ ".gif",
174
+ ".ico",
175
+ ".webp",
176
+ ".woff",
177
+ ".woff2",
178
+ ".ttf",
179
+ ".eot",
180
+ ".zip",
181
+ ".tar",
182
+ ".gz"
183
+ ];
184
+ const ext = path3.extname(srcPath).toLowerCase();
185
+ if (binaryExtensions.includes(ext)) {
186
+ await fs2.copy(srcPath, destPath);
187
+ return;
188
+ }
189
+ let content = await fs2.readFile(srcPath, "utf-8");
190
+ content = content.replace(/\{\{projectName\}\}/g, projectName);
191
+ if (config?.variables) {
192
+ for (const [key, value] of Object.entries(config.variables)) {
193
+ const placeholder = `{{${key}}}`;
194
+ const replacement = value === "{{projectName}}" ? projectName : value;
195
+ content = content.replace(new RegExp(placeholder.replace(/[{}]/g, "\\$&"), "g"), replacement);
196
+ }
197
+ }
198
+ await fs2.writeFile(destPath, content, "utf-8");
199
+ }
200
+ async function listTemplates() {
201
+ const templatesDir = getTemplatesDir();
202
+ const registryPath = path3.join(templatesDir, "template.config.json");
203
+ return fs2.readJson(registryPath);
204
+ }
205
+
206
+ // src/core/github-api.ts
207
+ var GITHUB_API_BASE = "https://api.github.com";
208
+ async function githubFetch(endpoint, token, options = {}) {
209
+ const url = `${GITHUB_API_BASE}${endpoint}`;
210
+ debug("github-api", `\u8BF7\u6C42: ${options.method || "GET"} ${endpoint}`);
211
+ try {
212
+ const response = await fetch(url, {
213
+ ...options,
214
+ headers: {
215
+ "Accept": "application/vnd.github+json",
216
+ "Authorization": `Bearer ${token}`,
217
+ "X-GitHub-Api-Version": "2022-11-28",
218
+ "User-Agent": "spec-go",
219
+ ...options.headers
220
+ }
221
+ });
222
+ debug("github-api", `\u54CD\u5E94\u72B6\u6001: ${response.status}`);
223
+ if (response.status === 403) {
224
+ const rateLimitRemaining = response.headers.get("x-ratelimit-remaining");
225
+ const rateLimitReset = response.headers.get("x-ratelimit-reset");
226
+ debug("github-api", `Rate Limit \u4FE1\u606F`, { rateLimitRemaining, rateLimitReset });
227
+ if (rateLimitRemaining === "0" && rateLimitReset) {
228
+ const resetDate = new Date(parseInt(rateLimitReset) * 1e3);
229
+ return {
230
+ success: false,
231
+ error: "API \u8BF7\u6C42\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650",
232
+ statusCode: 403,
233
+ rateLimitReset: resetDate
234
+ };
235
+ }
236
+ }
237
+ if (response.status === 401) {
238
+ debug("github-api", "Token \u9A8C\u8BC1\u5931\u8D25");
239
+ return {
240
+ success: false,
241
+ error: "Token \u65E0\u6548\u6216\u5DF2\u8FC7\u671F",
242
+ statusCode: 401
243
+ };
244
+ }
245
+ if (!response.ok) {
246
+ const errorData = await response.json();
247
+ debug("github-api", "\u8BF7\u6C42\u5931\u8D25", errorData);
248
+ return {
249
+ success: false,
250
+ error: errorData.message || `\u8BF7\u6C42\u5931\u8D25: ${response.status}`,
251
+ statusCode: response.status
252
+ };
253
+ }
254
+ const data = await response.json();
255
+ debug("github-api", "\u8BF7\u6C42\u6210\u529F");
256
+ return { success: true, data };
257
+ } catch (err) {
258
+ debug("github-api", "\u7F51\u7EDC\u8BF7\u6C42\u5F02\u5E38", { error: err instanceof Error ? err.message : String(err) });
259
+ return {
260
+ success: false,
261
+ error: err instanceof Error ? err.message : "\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"
262
+ };
263
+ }
264
+ }
265
+ async function validateToken(token) {
266
+ return githubFetch("/user", token);
267
+ }
268
+ async function createRepository(token, options) {
269
+ const endpoint = options.org ? `/orgs/${options.org}/repos` : "/user/repos";
270
+ const body = {
271
+ name: options.name,
272
+ description: options.description || `Created with spec-go`,
273
+ private: options.isPrivate,
274
+ auto_init: false
275
+ };
276
+ return githubFetch(endpoint, token, {
277
+ method: "POST",
278
+ body: JSON.stringify(body)
279
+ });
280
+ }
281
+
282
+ // src/core/git.ts
283
+ async function initGit(targetDir) {
284
+ debug("git", `\u521D\u59CB\u5316 Git \u4ED3\u5E93: ${targetDir}`);
285
+ await execAsync("git", ["init"], { cwd: targetDir });
286
+ await execAsync("git", ["add", "-A"], { cwd: targetDir });
287
+ await execAsync("git", ["commit", "-m", "Initial commit"], { cwd: targetDir });
288
+ debug("git", "Git \u521D\u59CB\u5316\u5B8C\u6210");
289
+ }
290
+ async function createGithubRepoOnly(repoName, isPublic, organization) {
291
+ const config = loadConfig();
292
+ if (!config.github?.token) {
293
+ return {
294
+ success: false,
295
+ error: "\u672A\u914D\u7F6E GitHub Token\uFF0C\u8BF7\u8FD0\u884C spec-go config --setup-github \u914D\u7F6E"
296
+ };
297
+ }
298
+ const token = config.github.token;
299
+ const defaultOrg = organization || config.github.defaultOrg;
300
+ const validateResult = await validateToken(token);
301
+ if (!validateResult.success) {
302
+ return {
303
+ success: false,
304
+ error: `GitHub Token \u65E0\u6548: ${validateResult.error}`
305
+ };
306
+ }
307
+ const createResult = await createRepository(token, {
308
+ name: repoName,
309
+ isPrivate: !isPublic,
310
+ org: defaultOrg
311
+ });
312
+ if (!createResult.success) {
313
+ if (createResult.statusCode === 422) {
314
+ return { success: false, error: `\u4ED3\u5E93 "${repoName}" \u5DF2\u5B58\u5728` };
315
+ }
316
+ return { success: false, error: createResult.error };
317
+ }
318
+ return {
319
+ success: true,
320
+ repoUrl: createResult.data.html_url
321
+ };
322
+ }
323
+
324
+ // src/core/post-init.ts
325
+ import path4 from "path";
326
+
327
+ // src/mcp/tools.ts
328
+ var createProjectSchema = z.object({
329
+ projectName: z.string().describe("\u9879\u76EE\u540D\u79F0"),
330
+ template: z.string().describe("\u6A21\u677F\u540D\u79F0\uFF0C\u5982 node-ts, react-ts, vue-ts \u7B49"),
331
+ targetDir: z.string().optional().describe("\u76EE\u6807\u76EE\u5F55\uFF0C\u9ED8\u8BA4\u4E3A\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u9879\u76EE\u540D\u79F0"),
332
+ skipGit: z.boolean().optional().default(false).describe("\u662F\u5426\u8DF3\u8FC7 Git \u521D\u59CB\u5316"),
333
+ skipInstall: z.boolean().optional().default(false).describe("\u662F\u5426\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5")
334
+ });
335
+ var validateProjectNameSchema = z.object({
336
+ name: z.string().describe("\u8981\u9A8C\u8BC1\u7684\u9879\u76EE\u540D\u79F0")
337
+ });
338
+ var initGitRepoSchema = z.object({
339
+ targetDir: z.string().describe("\u76EE\u6807\u76EE\u5F55\u7684\u7EDD\u5BF9\u8DEF\u5F84")
340
+ });
341
+ var createGithubRepoSchema = z.object({
342
+ repoName: z.string().describe("\u4ED3\u5E93\u540D\u79F0"),
343
+ targetDir: z.string().describe("\u672C\u5730\u9879\u76EE\u76EE\u5F55\u7684\u7EDD\u5BF9\u8DEF\u5F84"),
344
+ isPublic: z.boolean().optional().default(false).describe("\u662F\u5426\u521B\u5EFA\u516C\u5F00\u4ED3\u5E93"),
345
+ organization: z.string().optional().describe("GitHub \u7EC4\u7EC7\u540D\u79F0\uFF0C\u4E0D\u586B\u5219\u521B\u5EFA\u5728\u4E2A\u4EBA\u8D26\u6237\u4E0B")
346
+ });
347
+ async function createProject(params) {
348
+ const { projectName, template, targetDir, skipGit, skipInstall } = params;
349
+ const validName = toValidPackageName(projectName);
350
+ if (!isValidPackageName(validName)) {
351
+ return {
352
+ success: false,
353
+ error: `\u65E0\u6548\u7684\u9879\u76EE\u540D\u79F0: ${projectName}`
354
+ };
355
+ }
356
+ const registry = await listTemplates();
357
+ const templateEntry = registry.templates.find((t) => t.name === template);
358
+ if (!templateEntry) {
359
+ const availableTemplates = registry.templates.map((t) => t.name).join(", ");
360
+ return {
361
+ success: false,
362
+ error: `\u672A\u627E\u5230\u6A21\u677F "${template}"\uFF0C\u53EF\u7528\u6A21\u677F: ${availableTemplates}`
363
+ };
364
+ }
365
+ const resolvedTargetDir = targetDir ? path5.resolve(targetDir) : path5.resolve(process.cwd(), validName);
366
+ const options = {
367
+ projectName: validName,
368
+ template,
369
+ targetDir: resolvedTargetDir,
370
+ initGit: !skipGit,
371
+ createGithub: false,
372
+ isPublic: false,
373
+ noInstall: skipInstall
374
+ };
375
+ try {
376
+ const templateConfig = await scaffoldProject(options);
377
+ if (!skipInstall && templateConfig?.postInit) {
378
+ for (const cmd of templateConfig.postInit) {
379
+ const [command, ...args] = cmd.command.split(" ");
380
+ await execAsync(command, args, { cwd: resolvedTargetDir, stdio: "pipe" });
381
+ }
382
+ }
383
+ if (!skipGit) {
384
+ await initGit(resolvedTargetDir);
385
+ }
386
+ return {
387
+ success: true,
388
+ projectPath: resolvedTargetDir,
389
+ template
390
+ };
391
+ } catch (err) {
392
+ return {
393
+ success: false,
394
+ error: err instanceof Error ? err.message : String(err)
395
+ };
396
+ }
397
+ }
398
+ async function getTemplateList() {
399
+ const registry = await listTemplates();
400
+ return {
401
+ templates: registry.templates.map((t) => ({
402
+ name: t.name,
403
+ displayName: t.displayName,
404
+ description: t.description,
405
+ category: t.category || "single"
406
+ }))
407
+ };
408
+ }
409
+ function validateProjectName(params) {
410
+ const { name } = params;
411
+ if (!name || !name.trim()) {
412
+ return {
413
+ valid: false,
414
+ error: "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
415
+ };
416
+ }
417
+ const normalizedName = toValidPackageName(name);
418
+ if (!isValidPackageName(normalizedName)) {
419
+ return {
420
+ valid: false,
421
+ error: `\u65E0\u6548\u7684\u9879\u76EE\u540D\u79F0: ${name}`
422
+ };
423
+ }
424
+ return {
425
+ valid: true,
426
+ normalizedName
427
+ };
428
+ }
429
+ async function initGitRepo(params) {
430
+ const { targetDir } = params;
431
+ try {
432
+ await initGit(targetDir);
433
+ return { success: true };
434
+ } catch (err) {
435
+ return {
436
+ success: false,
437
+ error: err instanceof Error ? err.message : String(err)
438
+ };
439
+ }
440
+ }
441
+ async function createGithubRepository(params) {
442
+ const { repoName, targetDir, isPublic, organization } = params;
443
+ const result = await createGithubRepoOnly(repoName, isPublic, organization);
444
+ if (!result.success) {
445
+ return result;
446
+ }
447
+ try {
448
+ const remoteResult = await execAsync(
449
+ "git",
450
+ ["remote", "add", "origin", `https://github.com/${organization || "USER"}/${repoName}.git`],
451
+ { cwd: targetDir }
452
+ );
453
+ if (remoteResult.code !== 0) {
454
+ await execAsync(
455
+ "git",
456
+ ["remote", "set-url", "origin", `https://github.com/${organization || "USER"}/${repoName}.git`],
457
+ { cwd: targetDir }
458
+ );
459
+ }
460
+ const pushResult = await execAsync(
461
+ "git",
462
+ ["push", "-u", "origin", "main"],
463
+ { cwd: targetDir }
464
+ );
465
+ if (pushResult.code !== 0) {
466
+ const pushMaster = await execAsync(
467
+ "git",
468
+ ["push", "-u", "origin", "master"],
469
+ { cwd: targetDir }
470
+ );
471
+ if (pushMaster.code !== 0) {
472
+ return {
473
+ success: true,
474
+ repoUrl: result.repoUrl,
475
+ error: `\u4ED3\u5E93\u5DF2\u521B\u5EFA\u4F46\u63A8\u9001\u5931\u8D25: ${pushResult.stderr || pushMaster.stderr}`
476
+ };
477
+ }
478
+ }
479
+ return {
480
+ success: true,
481
+ repoUrl: result.repoUrl
482
+ };
483
+ } catch (err) {
484
+ return {
485
+ success: true,
486
+ repoUrl: result.repoUrl,
487
+ error: `\u4ED3\u5E93\u5DF2\u521B\u5EFA\u4F46\u63A8\u9001\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`
488
+ };
489
+ }
490
+ }
491
+
492
+ // src/mcp/server.ts
493
+ function createMcpServer() {
494
+ const server = new McpServer({
495
+ name: "spec-go",
496
+ version: "0.2.5"
497
+ });
498
+ server.tool(
499
+ "create_project",
500
+ "\u4F7F\u7528\u6A21\u677F\u521B\u5EFA\u65B0\u9879\u76EE\u3002\u652F\u6301\u591A\u79CD\u6A21\u677F\u5982 node-ts, react-ts, vue-ts \u7B49\u3002",
501
+ createProjectSchema.shape,
502
+ async (params) => {
503
+ const result = await createProject(params);
504
+ return {
505
+ content: [
506
+ {
507
+ type: "text",
508
+ text: JSON.stringify(result, null, 2)
509
+ }
510
+ ]
511
+ };
512
+ }
513
+ );
514
+ server.tool(
515
+ "list_templates",
516
+ "\u5217\u51FA\u6240\u6709\u53EF\u7528\u7684\u9879\u76EE\u6A21\u677F\uFF0C\u5305\u62EC\u5355\u4F53\u9879\u76EE\u548C\u524D\u540E\u7AEF\u5206\u79BB\u9879\u76EE\u3002",
517
+ {},
518
+ async () => {
519
+ const result = await getTemplateList();
520
+ return {
521
+ content: [
522
+ {
523
+ type: "text",
524
+ text: JSON.stringify(result, null, 2)
525
+ }
526
+ ]
527
+ };
528
+ }
529
+ );
530
+ server.tool(
531
+ "validate_project_name",
532
+ "\u9A8C\u8BC1\u9879\u76EE\u540D\u79F0\u662F\u5426\u6709\u6548\uFF0C\u5E76\u8FD4\u56DE\u89C4\u8303\u5316\u540E\u7684\u540D\u79F0\u3002",
533
+ validateProjectNameSchema.shape,
534
+ async (params) => {
535
+ const result = validateProjectName(params);
536
+ return {
537
+ content: [
538
+ {
539
+ type: "text",
540
+ text: JSON.stringify(result, null, 2)
541
+ }
542
+ ]
543
+ };
544
+ }
545
+ );
546
+ server.tool(
547
+ "init_git_repo",
548
+ "\u5728\u6307\u5B9A\u76EE\u5F55\u521D\u59CB\u5316 Git \u4ED3\u5E93\uFF0C\u6267\u884C git init\u3001git add \u548C\u521D\u59CB\u63D0\u4EA4\u3002",
549
+ initGitRepoSchema.shape,
550
+ async (params) => {
551
+ const result = await initGitRepo(params);
552
+ return {
553
+ content: [
554
+ {
555
+ type: "text",
556
+ text: JSON.stringify(result, null, 2)
557
+ }
558
+ ]
559
+ };
560
+ }
561
+ );
562
+ server.tool(
563
+ "create_github_repo",
564
+ "\u521B\u5EFA GitHub \u4ED3\u5E93\u5E76\u5C06\u672C\u5730\u4EE3\u7801\u63A8\u9001\u5230\u8FDC\u7A0B\u3002\u9700\u8981\u5148\u914D\u7F6E GitHub Token\u3002",
565
+ createGithubRepoSchema.shape,
566
+ async (params) => {
567
+ const result = await createGithubRepository(params);
568
+ return {
569
+ content: [
570
+ {
571
+ type: "text",
572
+ text: JSON.stringify(result, null, 2)
573
+ }
574
+ ]
575
+ };
576
+ }
577
+ );
578
+ return server;
579
+ }
580
+ async function startServer() {
581
+ const server = createMcpServer();
582
+ const transport = new StdioServerTransport();
583
+ await server.connect(transport);
584
+ }
585
+
586
+ // src/mcp/index.ts
587
+ startServer().catch((err) => {
588
+ console.error("MCP Server \u542F\u52A8\u5931\u8D25:", err);
589
+ process.exit(1);
590
+ });
591
+ //# sourceMappingURL=index.js.map