@eaperezc/mcpgen 0.1.0 → 0.1.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/dist/cli/index.js CHANGED
@@ -18,7 +18,7 @@ async function exists(path) {
18
18
  }
19
19
  }
20
20
  function toolTemplate(className, toolName) {
21
- return `import { BaseTool } from 'mcpkit';
21
+ return `import { BaseTool } from '@eaperezc/mcpgen';
22
22
  import { z } from 'zod';
23
23
 
24
24
  /**
@@ -44,8 +44,32 @@ export class ${className} extends BaseTool {
44
44
  }
45
45
  `;
46
46
  }
47
+ function toolTestTemplate(className, toolName) {
48
+ return `import { describe, it, expect } from 'vitest';
49
+ import { createTestClient } from '@eaperezc/mcpgen/testing';
50
+ import { ${className} } from './${className}.js';
51
+
52
+ describe('${className}', () => {
53
+ it('should execute successfully', async () => {
54
+ const client = createTestClient();
55
+ client.registerTool(new ${className}());
56
+
57
+ const result = await client.callTool('${toolName}', { input: 'test' });
58
+
59
+ expect(result.content).toHaveProperty('result');
60
+ });
61
+
62
+ it('should require input parameter', async () => {
63
+ const client = createTestClient();
64
+ client.registerTool(new ${className}());
65
+
66
+ await expect(client.callTool('${toolName}', {})).rejects.toThrow();
67
+ });
68
+ });
69
+ `;
70
+ }
47
71
  function resourceTemplate(className, resourceName) {
48
- return `import { BaseResource } from 'mcpkit';
72
+ return `import { BaseResource } from '@eaperezc/mcpgen';
49
73
 
50
74
  /**
51
75
  * ${className} - Description of what this resource provides
@@ -70,7 +94,7 @@ export class ${className} extends BaseResource {
70
94
  `;
71
95
  }
72
96
  function promptTemplate(className, promptName) {
73
- return `import { BasePrompt } from 'mcpkit';
97
+ return `import { BasePrompt } from '@eaperezc/mcpgen';
74
98
  import { z } from 'zod';
75
99
 
76
100
  /**
@@ -119,18 +143,21 @@ async function generateComponent(options) {
119
143
  const typeDir = type === "tool" ? "tools" : type === "resource" ? "resources" : "prompts";
120
144
  const srcDir = join(process.cwd(), "src", typeDir);
121
145
  const filePath = join(srcDir, `${fileName}.ts`);
146
+ const testFilePath = join(srcDir, `${fileName}.test.ts`);
122
147
  const indexPath = join(srcDir, "index.ts");
123
148
  if (!await exists(join(process.cwd(), "src"))) {
124
- throw new Error('No src/ directory found. Are you in an mcpkit project? Run "mcpkit init" first.');
149
+ throw new Error('No src/ directory found. Are you in an mcpgen project? Run "mcpgen init" first.');
125
150
  }
126
151
  await mkdir(srcDir, { recursive: true });
127
152
  if (await exists(filePath)) {
128
153
  throw new Error(`${type} '${fileName}' already exists at ${filePath}`);
129
154
  }
130
155
  let content;
156
+ let testContent = null;
131
157
  switch (type) {
132
158
  case "tool":
133
159
  content = toolTemplate(className, kebabName);
160
+ testContent = toolTestTemplate(className, kebabName);
134
161
  break;
135
162
  case "resource":
136
163
  content = resourceTemplate(className, kebabName);
@@ -144,6 +171,10 @@ async function generateComponent(options) {
144
171
  await writeFile(filePath, content);
145
172
  console.log(`
146
173
  \u2705 Created ${type}: ${filePath.replace(process.cwd(), ".")}`);
174
+ if (testContent) {
175
+ await writeFile(testFilePath, testContent);
176
+ console.log(` Created test: ${testFilePath.replace(process.cwd(), ".")}`);
177
+ }
147
178
  await updateIndexFile(indexPath, className, fileName);
148
179
  console.log(` Updated: ${indexPath.replace(process.cwd(), ".")}`);
149
180
  console.log(`
@@ -152,8 +183,9 @@ Next steps:
152
183
  1. Edit src/${typeDir}/${fileName}.ts to implement your ${type}
153
184
  2. Register it in src/index.ts:
154
185
 
155
- import { ${className} } from './tools/${fileName}.js';
186
+ import { ${className} } from './${typeDir}/${fileName}.js';
156
187
  server.${type}(new ${className}());
188
+ 3. Run tests: npm test
157
189
  `);
158
190
  }
159
191
 
@@ -171,7 +203,8 @@ var packageJsonTemplate = (name, description) => `{
171
203
  "test": "vitest run",
172
204
  "test:watch": "vitest",
173
205
  "lint": "eslint src",
174
- "typecheck": "tsc --noEmit"
206
+ "typecheck": "tsc --noEmit",
207
+ "inspector": "npx @modelcontextprotocol/inspector"
175
208
  },
176
209
  "keywords": ["mcp", "model-context-protocol"],
177
210
  "license": "MIT",
@@ -336,9 +369,9 @@ export class ConfigResource extends BaseResource {
336
369
  var promptsIndexTemplate = () => `// Export your prompts here
337
370
  // export { SummarizePrompt } from './SummarizePrompt.js';
338
371
  `;
339
- var testExampleTemplate = () => `import { describe, it, expect } from 'vitest';
372
+ var greetToolTestTemplate = () => `import { describe, it, expect } from 'vitest';
340
373
  import { createTestClient } from '@eaperezc/mcpgen/testing';
341
- import { GreetTool } from '../src/tools/GreetTool.js';
374
+ import { GreetTool } from './GreetTool.js';
342
375
 
343
376
  describe('GreetTool', () => {
344
377
  it('should greet the user', async () => {
@@ -394,19 +427,32 @@ npm start
394
427
  npm test
395
428
  \`\`\`
396
429
 
430
+ ### MCP Inspector
431
+
432
+ To test and debug your server with the MCP Inspector:
433
+
434
+ \`\`\`bash
435
+ # Terminal 1: Start the server
436
+ npm run dev
437
+
438
+ # Terminal 2: Launch the inspector
439
+ npm run inspector
440
+ \`\`\`
441
+
442
+ Then connect to \`http://localhost:3000/mcp\` using **Streamable HTTP** transport.
443
+
397
444
  ## Project Structure
398
445
 
399
446
  \`\`\`
400
447
  ${name}/
401
448
  \u251C\u2500\u2500 src/
402
- \u2502 \u251C\u2500\u2500 tools/ # MCP tools
403
- \u2502 \u2502 \u2514\u2500\u2500 GreetTool.ts
404
- \u2502 \u251C\u2500\u2500 resources/ # MCP resources
449
+ \u2502 \u251C\u2500\u2500 tools/ # MCP tools
450
+ \u2502 \u2502 \u251C\u2500\u2500 GreetTool.ts
451
+ \u2502 \u2502 \u2514\u2500\u2500 GreetTool.test.ts
452
+ \u2502 \u251C\u2500\u2500 resources/ # MCP resources
405
453
  \u2502 \u2502 \u2514\u2500\u2500 ConfigResource.ts
406
- \u2502 \u251C\u2500\u2500 prompts/ # MCP prompts
407
- \u2502 \u2514\u2500\u2500 index.ts # Server entry point
408
- \u251C\u2500\u2500 tests/
409
- \u2502 \u2514\u2500\u2500 tools.test.ts
454
+ \u2502 \u251C\u2500\u2500 prompts/ # MCP prompts
455
+ \u2502 \u2514\u2500\u2500 index.ts # Server entry point
410
456
  \u251C\u2500\u2500 package.json
411
457
  \u2514\u2500\u2500 tsconfig.json
412
458
  \`\`\`
@@ -480,7 +526,7 @@ async function initProject(options) {
480
526
  const {
481
527
  name,
482
528
  description = `An MCP server built with @eaperezc/mcpgen`,
483
- transport = "stdio"
529
+ transport = "http"
484
530
  } = options;
485
531
  const projectDir = join(process.cwd(), name);
486
532
  if (await exists2(projectDir)) {
@@ -494,8 +540,7 @@ Creating new MCP server: ${name}
494
540
  join(projectDir, "src"),
495
541
  join(projectDir, "src", "tools"),
496
542
  join(projectDir, "src", "resources"),
497
- join(projectDir, "src", "prompts"),
498
- join(projectDir, "tests")
543
+ join(projectDir, "src", "prompts")
499
544
  ];
500
545
  for (const dir of dirs) {
501
546
  await mkdir(dir, { recursive: true });
@@ -510,10 +555,10 @@ Creating new MCP server: ${name}
510
555
  { path: "src/index.ts", content: mainIndexTemplate(name, transport) },
511
556
  { path: "src/tools/index.ts", content: toolsIndexTemplate() },
512
557
  { path: "src/tools/GreetTool.ts", content: greetToolTemplate() },
558
+ { path: "src/tools/GreetTool.test.ts", content: greetToolTestTemplate() },
513
559
  { path: "src/resources/index.ts", content: resourcesIndexTemplate() },
514
560
  { path: "src/resources/ConfigResource.ts", content: configResourceTemplate(name) },
515
- { path: "src/prompts/index.ts", content: promptsIndexTemplate() },
516
- { path: "tests/tools.test.ts", content: testExampleTemplate() }
561
+ { path: "src/prompts/index.ts", content: promptsIndexTemplate() }
517
562
  ];
518
563
  for (const file of files) {
519
564
  const filePath = join(projectDir, file.path);
@@ -543,7 +588,7 @@ Happy building! \u{1F680}
543
588
  // src/cli/index.ts
544
589
  var program = new Command();
545
590
  program.name("mcpgen").description("CLI for building MCP servers").version("0.1.0");
546
- program.command("init").description("Initialize a new MCP server project").argument("<name>", "Project name").option("-d, --description <desc>", "Project description").option("-t, --transport <type>", "Transport type (stdio or http)", "stdio").option("--skip-install", "Skip npm install").action(async (name, options) => {
591
+ program.command("init").description("Initialize a new MCP server project").argument("<name>", "Project name").option("-d, --description <desc>", "Project description").option("-t, --transport <type>", "Transport type (http or stdio)", "http").option("--skip-install", "Skip npm install").action(async (name, options) => {
547
592
  try {
548
593
  await initProject({
549
594
  name,
@@ -592,14 +637,15 @@ program.addHelpText(
592
637
  "after",
593
638
  `
594
639
  Examples:
595
- $ mcpgen init my-mcp-server Create a new MCP server project
596
- $ mcpgen init my-api --transport http Create with HTTP transport
640
+ $ mcpgen init my-mcp-server Create a new MCP server (HTTP)
641
+ $ mcpgen init my-api --transport stdio Create with stdio transport
597
642
  $ mcpgen make:tool search Create a new tool
598
643
  $ mcpgen make:resource database Create a new resource
599
644
  $ mcpgen make:prompt summarize Create a new prompt
600
645
  `
601
646
  );
602
647
  if (process.argv.length <= 2) {
648
+ const yellow = "\x1B[33m";
603
649
  const cyan = "\x1B[36m";
604
650
  const dim = "\x1B[2m";
605
651
  const bold = "\x1B[1m";
@@ -607,7 +653,7 @@ if (process.argv.length <= 2) {
607
653
  console.log(`
608
654
  ${dim}+-------------------------------------+${reset}
609
655
  ${dim}|${reset} ${dim}|${reset}
610
- ${dim}|${reset} ${bold}${cyan}MCPGEN${reset} ${dim}v0.1.0${reset} ${dim}|${reset}
656
+ ${dim}|${reset} ${bold}${yellow}MCP-GEN${reset} ${dim}v0.1.0${reset} ${dim}|${reset}
611
657
  ${dim}|${reset} ${dim}|${reset}
612
658
  ${dim}|${reset} A TypeScript framework for ${dim}|${reset}
613
659
  ${dim}|${reset} building MCP servers ${dim}|${reset}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/generate.ts","../../src/cli/templates/index.ts","../../src/cli/commands/init.ts","../../src/cli/index.ts"],"names":["exists","access","join","mkdir","writeFile"],"mappings":"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","file":"index.js","sourcesContent":["import { mkdir, writeFile, access, readFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\n\nexport type ComponentType = 'tool' | 'resource' | 'prompt';\n\nexport interface GenerateOptions {\n type: ComponentType;\n name: string;\n}\n\n/**\n * Convert a name to PascalCase\n */\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert a name to kebab-case\n */\nfunction toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Check if a file exists\n */\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate tool template\n */\nfunction toolTemplate(className: string, toolName: string): string {\n return `import { BaseTool } from 'mcpkit';\nimport { z } from 'zod';\n\n/**\n * ${className} - Description of what this tool does\n */\nexport class ${className} extends BaseTool {\n name = '${toolName}';\n description = 'TODO: Add description';\n\n schema = z.object({\n // TODO: Define your input schema\n input: z.string().describe('Input parameter'),\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n // TODO: Implement your tool logic\n return {\n content: {\n result: \\`Processed: \\${input.input}\\`,\n },\n };\n }\n}\n`;\n}\n\n/**\n * Generate resource template\n */\nfunction resourceTemplate(className: string, resourceName: string): string {\n return `import { BaseResource } from 'mcpkit';\n\n/**\n * ${className} - Description of what this resource provides\n */\nexport class ${className} extends BaseResource {\n uri = '${resourceName}://data';\n name = '${className}';\n description = 'TODO: Add description';\n\n async read() {\n // TODO: Implement your resource logic\n return {\n contents: [\n this.json({\n // Your data here\n example: 'data',\n }),\n ],\n };\n }\n}\n`;\n}\n\n/**\n * Generate prompt template\n */\nfunction promptTemplate(className: string, promptName: string): string {\n return `import { BasePrompt } from 'mcpkit';\nimport { z } from 'zod';\n\n/**\n * ${className} - Description of what this prompt does\n */\nexport class ${className} extends BasePrompt {\n name = '${promptName}';\n description = 'TODO: Add description';\n\n arguments = z.object({\n // TODO: Define your arguments schema\n topic: z.string().describe('The topic to discuss'),\n });\n\n async render(args: z.infer<typeof this.arguments>) {\n // TODO: Implement your prompt logic\n return {\n messages: [\n this.user(\\`Please help me with: \\${args.topic}\\`),\n ],\n };\n }\n}\n`;\n}\n\n/**\n * Update index file to export the new component\n */\nasync function updateIndexFile(indexPath: string, className: string, fileName: string): Promise<void> {\n let content = '';\n\n if (await exists(indexPath)) {\n content = await readFile(indexPath, 'utf-8');\n }\n\n const exportLine = `export { ${className} } from './${fileName}.js';`;\n\n if (!content.includes(exportLine)) {\n // Remove comments and empty lines at the start for clean exports\n const lines = content.split('\\n').filter(line =>\n line.trim() && !line.trim().startsWith('//')\n );\n lines.push(exportLine);\n content = lines.join('\\n') + '\\n';\n await writeFile(indexPath, content);\n }\n}\n\n/**\n * Generate a new component\n */\nexport async function generateComponent(options: GenerateOptions): Promise<void> {\n const { type, name } = options;\n\n const className = toPascalCase(name) + (type === 'tool' ? 'Tool' : type === 'resource' ? 'Resource' : 'Prompt');\n const fileName = className;\n const kebabName = toKebabCase(name);\n\n // Determine directory\n const typeDir = type === 'tool' ? 'tools' : type === 'resource' ? 'resources' : 'prompts';\n const srcDir = join(process.cwd(), 'src', typeDir);\n const filePath = join(srcDir, `${fileName}.ts`);\n const indexPath = join(srcDir, 'index.ts');\n\n // Check if src directory exists (are we in an mcpkit project?)\n if (!(await exists(join(process.cwd(), 'src')))) {\n throw new Error('No src/ directory found. Are you in an mcpkit project? Run \"mcpkit init\" first.');\n }\n\n // Create directory if it doesn't exist\n await mkdir(srcDir, { recursive: true });\n\n // Check if file already exists\n if (await exists(filePath)) {\n throw new Error(`${type} '${fileName}' already exists at ${filePath}`);\n }\n\n // Generate content based on type\n let content: string;\n switch (type) {\n case 'tool':\n content = toolTemplate(className, kebabName);\n break;\n case 'resource':\n content = resourceTemplate(className, kebabName);\n break;\n case 'prompt':\n content = promptTemplate(className, kebabName);\n break;\n default:\n throw new Error(`Unknown component type: ${type}`);\n }\n\n // Write file\n await writeFile(filePath, content);\n console.log(`\\n✅ Created ${type}: ${filePath.replace(process.cwd(), '.')}`);\n\n // Update index file\n await updateIndexFile(indexPath, className, fileName);\n console.log(` Updated: ${indexPath.replace(process.cwd(), '.')}`);\n\n console.log(`\nNext steps:\n\n 1. Edit src/${typeDir}/${fileName}.ts to implement your ${type}\n 2. Register it in src/index.ts:\n\n import { ${className} } from './tools/${fileName}.js';\n server.${type}(new ${className}());\n`);\n}\n","/**\n * Templates for CLI scaffolding\n */\n\nexport const packageJsonTemplate = (name: string, description: string) => `{\n \"name\": \"${name}\",\n \"version\": \"0.1.0\",\n \"description\": \"${description}\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"dev\": \"tsx watch src/index.ts\",\n \"start\": \"node dist/index.js\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"keywords\": [\"mcp\", \"model-context-protocol\"],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@eaperezc/mcpgen\": \"^0.1.0\",\n \"@modelcontextprotocol/sdk\": \"^1.11.0\",\n \"zod\": \"^3.23.8\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.10.0\",\n \"typescript\": \"^5.7.2\",\n \"tsx\": \"^4.19.2\",\n \"vitest\": \"^2.1.8\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n`;\n\nexport const tsconfigTemplate = () => `{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"lib\": [\"ES2022\"],\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"declaration\": true,\n \"outDir\": \"./dist\",\n \"rootDir\": \"./src\",\n \"resolveJsonModule\": true\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n`;\n\nexport const gitignoreTemplate = () => `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n\n# Environment files\n.env\n.env.local\n.env.*.local\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\n`;\n\nexport const mainIndexTemplate = (name: string, transport: 'stdio' | 'http') => {\n if (transport === 'http') {\n return `import { McpServer } from '@eaperezc/mcpgen';\nimport { GreetTool } from './tools/GreetTool.js';\nimport { ConfigResource } from './resources/ConfigResource.js';\n\nconst server = new McpServer({\n name: '${name}',\n version: '0.1.0',\n transport: {\n type: 'http',\n port: 3000,\n cors: { origin: '*' },\n },\n logging: { level: 'info' },\n});\n\n// Register tools\nserver.tool(new GreetTool());\n\n// Register resources\nserver.resource(new ConfigResource());\n\n// Start the server\nserver.start().then(() => {\n console.log('MCP server running at http://localhost:3000/mcp');\n});\n`;\n }\n\n return `import { McpServer } from '@eaperezc/mcpgen';\nimport { GreetTool } from './tools/GreetTool.js';\nimport { ConfigResource } from './resources/ConfigResource.js';\n\nconst server = new McpServer({\n name: '${name}',\n version: '0.1.0',\n logging: { level: 'info' },\n});\n\n// Register tools\nserver.tool(new GreetTool());\n\n// Register resources\nserver.resource(new ConfigResource());\n\n// Start the server\nserver.start();\n`;\n};\n\nexport const toolsIndexTemplate = () => `export { GreetTool } from './GreetTool.js';\n`;\n\nexport const greetToolTemplate = () => `import { BaseTool } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\n/**\n * Example tool that greets a user\n */\nexport class GreetTool extends BaseTool {\n name = 'greet';\n description = 'Greets a user by name';\n\n schema = z.object({\n name: z.string().describe('The name of the person to greet'),\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n return {\n content: {\n greeting: \\`Hello, \\${input.name}! Welcome to your MCP server.\\`,\n },\n };\n }\n}\n`;\n\nexport const resourcesIndexTemplate = () => `export { ConfigResource } from './ConfigResource.js';\n`;\n\nexport const configResourceTemplate = (name: string) => `import { BaseResource } from '@eaperezc/mcpgen';\n\n/**\n * Example resource that provides server configuration\n */\nexport class ConfigResource extends BaseResource {\n uri = 'config://server';\n name = 'Server Configuration';\n description = 'Provides server configuration information';\n\n async read() {\n return {\n contents: [\n this.json({\n serverName: '${name}',\n version: '0.1.0',\n environment: process.env.NODE_ENV ?? 'development',\n }),\n ],\n };\n }\n}\n`;\n\nexport const promptsIndexTemplate = () => `// Export your prompts here\n// export { SummarizePrompt } from './SummarizePrompt.js';\n`;\n\nexport const testExampleTemplate = () => `import { describe, it, expect } from 'vitest';\nimport { createTestClient } from '@eaperezc/mcpgen/testing';\nimport { GreetTool } from '../src/tools/GreetTool.js';\n\ndescribe('GreetTool', () => {\n it('should greet the user', async () => {\n const client = createTestClient();\n client.registerTool(new GreetTool());\n\n const result = await client.callTool('greet', { name: 'Alice' });\n\n expect(result.content).toHaveProperty('greeting');\n expect((result.content as { greeting: string }).greeting).toContain('Alice');\n });\n\n it('should require a name', async () => {\n const client = createTestClient();\n client.registerTool(new GreetTool());\n\n await expect(client.callTool('greet', {})).rejects.toThrow();\n });\n});\n`;\n\nexport const readmeTemplate = (name: string, description: string) => `# ${name}\n\n${description}\n\n## Getting Started\n\n### Installation\n\n\\`\\`\\`bash\nnpm install\n\\`\\`\\`\n\n### Development\n\nRun the server in development mode with hot reload:\n\n\\`\\`\\`bash\nnpm run dev\n\\`\\`\\`\n\n### Production\n\nBuild and run:\n\n\\`\\`\\`bash\nnpm run build\nnpm start\n\\`\\`\\`\n\n### Testing\n\n\\`\\`\\`bash\nnpm test\n\\`\\`\\`\n\n## Project Structure\n\n\\`\\`\\`\n${name}/\n├── src/\n│ ├── tools/ # MCP tools\n│ │ └── GreetTool.ts\n│ ├── resources/ # MCP resources\n│ │ └── ConfigResource.ts\n│ ├── prompts/ # MCP prompts\n│ └── index.ts # Server entry point\n├── tests/\n│ └── tools.test.ts\n├── package.json\n└── tsconfig.json\n\\`\\`\\`\n\n## Adding New Components\n\n### Tools\n\nCreate a new file in \\`src/tools/\\`:\n\n\\`\\`\\`typescript\nimport { BaseTool } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\nexport class MyTool extends BaseTool {\n name = 'my-tool';\n description = 'Description of what this tool does';\n\n schema = z.object({\n // Define your input schema\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n // Implement your tool logic\n return { content: { result: 'success' } };\n }\n}\n\\`\\`\\`\n\n### Resources\n\nCreate a new file in \\`src/resources/\\`:\n\n\\`\\`\\`typescript\nimport { BaseResource } from '@eaperezc/mcpgen';\n\nexport class MyResource extends BaseResource {\n uri = 'my-resource://example';\n name = 'My Resource';\n\n async read() {\n return { contents: [this.json({ data: 'example' })] };\n }\n}\n\\`\\`\\`\n\n## License\n\nMIT\n`;\n\nexport const vitestConfigTemplate = () => `import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environment: 'node',\n },\n});\n`;\n","import { mkdir, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n packageJsonTemplate,\n tsconfigTemplate,\n gitignoreTemplate,\n mainIndexTemplate,\n toolsIndexTemplate,\n greetToolTemplate,\n resourcesIndexTemplate,\n configResourceTemplate,\n promptsIndexTemplate,\n testExampleTemplate,\n readmeTemplate,\n vitestConfigTemplate,\n} from '../templates/index.js';\n\nexport interface InitOptions {\n name: string;\n description?: string;\n transport?: 'stdio' | 'http';\n skipInstall?: boolean;\n}\n\n/**\n * Check if a directory exists\n */\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Initialize a new MCP server project\n */\nexport async function initProject(options: InitOptions): Promise<void> {\n const {\n name,\n description = `An MCP server built with @eaperezc/mcpgen`,\n transport = 'stdio',\n } = options;\n\n const projectDir = join(process.cwd(), name);\n\n // Check if directory already exists\n if (await exists(projectDir)) {\n throw new Error(`Directory '${name}' already exists`);\n }\n\n console.log(`\\nCreating new MCP server: ${name}\\n`);\n\n // Create directories\n const dirs = [\n projectDir,\n join(projectDir, 'src'),\n join(projectDir, 'src', 'tools'),\n join(projectDir, 'src', 'resources'),\n join(projectDir, 'src', 'prompts'),\n join(projectDir, 'tests'),\n ];\n\n for (const dir of dirs) {\n await mkdir(dir, { recursive: true });\n console.log(` Created: ${dir.replace(process.cwd(), '.')}`);\n }\n\n // Create files\n const files: Array<{ path: string; content: string }> = [\n { path: 'package.json', content: packageJsonTemplate(name, description) },\n { path: 'tsconfig.json', content: tsconfigTemplate() },\n { path: '.gitignore', content: gitignoreTemplate() },\n { path: 'vitest.config.ts', content: vitestConfigTemplate() },\n { path: 'README.md', content: readmeTemplate(name, description) },\n { path: 'src/index.ts', content: mainIndexTemplate(name, transport) },\n { path: 'src/tools/index.ts', content: toolsIndexTemplate() },\n { path: 'src/tools/GreetTool.ts', content: greetToolTemplate() },\n { path: 'src/resources/index.ts', content: resourcesIndexTemplate() },\n { path: 'src/resources/ConfigResource.ts', content: configResourceTemplate(name) },\n { path: 'src/prompts/index.ts', content: promptsIndexTemplate() },\n { path: 'tests/tools.test.ts', content: testExampleTemplate() },\n ];\n\n for (const file of files) {\n const filePath = join(projectDir, file.path);\n await writeFile(filePath, file.content);\n console.log(` Created: ./${name}/${file.path}`);\n }\n\n console.log(`\n✅ Project created successfully!\n\nNext steps:\n\n cd ${name}\n npm install\n npm run dev\n\n${transport === 'http' ? 'Server will run at http://localhost:3000/mcp' : 'Server will run via stdio'}\n\nTo add new components:\n - Tools: Create files in src/tools/\n - Resources: Create files in src/resources/\n - Prompts: Create files in src/prompts/\n\nHappy building! 🚀\n`);\n}\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { generateComponent } from './commands/generate.js';\nimport { initProject } from './commands/init.js';\n\nconst program = new Command();\n\nprogram.name('mcpgen').description('CLI for building MCP servers').version('0.1.0');\n\n// Init command\nprogram\n .command('init')\n .description('Initialize a new MCP server project')\n .argument('<name>', 'Project name')\n .option('-d, --description <desc>', 'Project description')\n .option('-t, --transport <type>', 'Transport type (stdio or http)', 'stdio')\n .option('--skip-install', 'Skip npm install')\n .action(async (name: string, options) => {\n try {\n await initProject({\n name,\n description: options.description,\n transport: options.transport as 'stdio' | 'http',\n skipInstall: options.skipInstall,\n });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:tool command\nprogram\n .command('make:tool')\n .description('Create a new tool')\n .argument('<name>', 'Tool name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'tool', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:resource command\nprogram\n .command('make:resource')\n .description('Create a new resource')\n .argument('<name>', 'Resource name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'resource', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:prompt command\nprogram\n .command('make:prompt')\n .description('Create a new prompt')\n .argument('<name>', 'Prompt name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'prompt', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// Add examples to help\nprogram.addHelpText(\n 'after',\n `\nExamples:\n $ mcpgen init my-mcp-server Create a new MCP server project\n $ mcpgen init my-api --transport http Create with HTTP transport\n $ mcpgen make:tool search Create a new tool\n $ mcpgen make:resource database Create a new resource\n $ mcpgen make:prompt summarize Create a new prompt\n`\n);\n\n// Show welcome message if no arguments provided\nif (process.argv.length <= 2) {\n const cyan = '\\x1b[36m';\n const dim = '\\x1b[2m';\n const bold = '\\x1b[1m';\n const reset = '\\x1b[0m';\n\n console.log(`\n${dim}+-------------------------------------+${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} ${bold}${cyan}MCPGEN${reset} ${dim}v0.1.0${reset} ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} A TypeScript framework for ${dim}|${reset}\n${dim}|${reset} building MCP servers ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} Run ${cyan}mcpgen --help${reset} for commands ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}+-------------------------------------+${reset}\n`);\n} else {\n program.parse();\n}\n"]}
1
+ {"version":3,"sources":["../../src/cli/commands/generate.ts","../../src/cli/templates/index.ts","../../src/cli/commands/init.ts","../../src/cli/index.ts"],"names":["exists","access","join","mkdir","writeFile"],"mappings":";;;;;AAaA,SAAS,aAAa,GAAA,EAAqB;AACzC,EAAA,OAAO,GAAA,CACJ,MAAM,SAAS,CAAA,CACf,IAAI,CAAC,IAAA,KAAS,KAAK,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY,GAAI,KAAK,KAAA,CAAM,CAAC,EAAE,WAAA,EAAa,CAAA,CACxE,IAAA,CAAK,EAAE,CAAA;AACZ;AAKA,SAAS,YAAY,GAAA,EAAqB;AACxC,EAAA,OAAO,GAAA,CACJ,QAAQ,iBAAA,EAAmB,OAAO,EAClC,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CACtB,WAAA,EAAY;AACjB;AAKA,eAAe,OAAO,IAAA,EAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,IAAI,CAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,SAAS,YAAA,CAAa,WAAmB,QAAA,EAA0B;AACjE,EAAA,OAAO,CAAA;AAAA;;AAAA;AAAA,GAAA,EAIJ,SAAS,CAAA;AAAA;AAAA,aAAA,EAEC,SAAS,CAAA;AAAA,UAAA,EACZ,QAAQ,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAkBpB;AAKA,SAAS,gBAAA,CAAiB,WAAmB,QAAA,EAA0B;AACrE,EAAA,OAAO,CAAA;AAAA;AAAA,SAAA,EAEE,SAAS,cAAc,SAAS,CAAA;;AAAA,UAAA,EAE/B,SAAS,CAAA;AAAA;AAAA;AAAA,4BAAA,EAGS,SAAS,CAAA;;AAAA,0CAAA,EAEK,QAAQ,CAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,4BAAA,EAOtB,SAAS,CAAA;;AAAA,kCAAA,EAEH,QAAQ,CAAA;AAAA;AAAA;AAAA,CAAA;AAI5C;AAKA,SAAS,gBAAA,CAAiB,WAAmB,YAAA,EAA8B;AACzE,EAAA,OAAO,CAAA;;AAAA;AAAA,GAAA,EAGJ,SAAS,CAAA;AAAA;AAAA,aAAA,EAEC,SAAS,CAAA;AAAA,SAAA,EACb,YAAY,CAAA;AAAA,UAAA,EACX,SAAS,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAgBrB;AAKA,SAAS,cAAA,CAAe,WAAmB,UAAA,EAA4B;AACrE,EAAA,OAAO,CAAA;AAAA;;AAAA;AAAA,GAAA,EAIJ,SAAS,CAAA;AAAA;AAAA,aAAA,EAEC,SAAS,CAAA;AAAA,UAAA,EACZ,UAAU,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAkBtB;AAKA,eAAe,eAAA,CAAgB,SAAA,EAAmB,SAAA,EAAmB,QAAA,EAAiC;AACpG,EAAA,IAAI,OAAA,GAAU,EAAA;AAEd,EAAA,IAAI,MAAM,MAAA,CAAO,SAAS,CAAA,EAAG;AAC3B,IAAA,OAAA,GAAU,MAAM,QAAA,CAAS,SAAA,EAAW,OAAO,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,UAAA,GAAa,CAAA,SAAA,EAAY,SAAS,CAAA,WAAA,EAAc,QAAQ,CAAA,KAAA,CAAA;AAE9D,EAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,EAAG;AAEjC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,CAAE,MAAA;AAAA,MAAO,CAAA,IAAA,KACvC,KAAK,IAAA,EAAK,IAAK,CAAC,IAAA,CAAK,IAAA,EAAK,CAAE,UAAA,CAAW,IAAI;AAAA,KAC7C;AACA,IAAA,KAAA,CAAM,KAAK,UAAU,CAAA;AACrB,IAAA,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC7B,IAAA,MAAM,SAAA,CAAU,WAAW,OAAO,CAAA;AAAA,EACpC;AACF;AAKA,eAAsB,kBAAkB,OAAA,EAAyC;AAC/E,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,OAAA;AAEvB,EAAA,MAAM,SAAA,GAAY,aAAa,IAAI,CAAA,IAAK,SAAS,MAAA,GAAS,MAAA,GAAS,IAAA,KAAS,UAAA,GAAa,UAAA,GAAa,QAAA,CAAA;AACtG,EAAA,MAAM,QAAA,GAAW,SAAA;AACjB,EAAA,MAAM,SAAA,GAAY,YAAY,IAAI,CAAA;AAGlC,EAAA,MAAM,UAAU,IAAA,KAAS,MAAA,GAAS,OAAA,GAAU,IAAA,KAAS,aAAa,WAAA,GAAc,SAAA;AAChF,EAAA,MAAM,SAAS,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAI,EAAG,OAAO,OAAO,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,QAAQ,CAAA,GAAA,CAAK,CAAA;AAC9C,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,QAAQ,CAAA,QAAA,CAAU,CAAA;AACvD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,EAAQ,UAAU,CAAA;AAGzC,EAAA,IAAI,CAAE,MAAM,MAAA,CAAO,IAAA,CAAK,QAAQ,GAAA,EAAI,EAAG,KAAK,CAAC,CAAA,EAAI;AAC/C,IAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,EACnG;AAGA,EAAA,MAAM,KAAA,CAAM,MAAA,EAAQ,EAAE,SAAA,EAAW,MAAM,CAAA;AAGvC,EAAA,IAAI,MAAM,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,MAAM,CAAA,EAAG,IAAI,KAAK,QAAQ,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAE,CAAA;AAAA,EACvE;AAGA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,MAAA;AACH,MAAA,OAAA,GAAU,YAAA,CAAa,WAAW,SAAS,CAAA;AAC3C,MAAA,WAAA,GAAc,gBAAA,CAAiB,WAAW,SAAS,CAAA;AACnD,MAAA;AAAA,IACF,KAAK,UAAA;AACH,MAAA,OAAA,GAAU,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC/C,MAAA;AAAA,IACF,KAAK,QAAA;AACH,MAAA,OAAA,GAAU,cAAA,CAAe,WAAW,SAAS,CAAA;AAC7C,MAAA;AAAA,IACF;AACE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAI,CAAA,CAAE,CAAA;AAAA;AAIrD,EAAA,MAAM,SAAA,CAAU,UAAU,OAAO,CAAA;AACjC,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,eAAA,EAAe,IAAI,KAAK,QAAA,CAAS,OAAA,CAAQ,QAAQ,GAAA,EAAI,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAG1E,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,SAAA,CAAU,cAAc,WAAW,CAAA;AACzC,IAAA,OAAA,CAAQ,GAAA,CAAI,oBAAoB,YAAA,CAAa,OAAA,CAAQ,QAAQ,GAAA,EAAI,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,EAC5E;AAGA,EAAA,MAAM,eAAA,CAAgB,SAAA,EAAW,SAAA,EAAW,QAAQ,CAAA;AACpD,EAAA,OAAA,CAAQ,GAAA,CAAI,eAAe,SAAA,CAAU,OAAA,CAAQ,QAAQ,GAAA,EAAI,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAElE,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA;;AAAA,cAAA,EAGE,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA,sBAAA,EAAyB,IAAI;AAAA;;AAAA,cAAA,EAGhD,SAAS,CAAA,WAAA,EAAc,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA;AAAA,YAAA,EAC5C,IAAI,QAAQ,SAAS,CAAA;AAAA;AAAA,CAElC,CAAA;AACD;;;AC5PO,IAAM,mBAAA,GAAsB,CAAC,IAAA,EAAc,WAAA,KAAwB,CAAA;AAAA,WAAA,EAC7D,IAAI,CAAA;AAAA;AAAA,kBAAA,EAEG,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAgCxB,IAAM,mBAAmB,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAoB/B,IAAM,oBAAoB,MAAM,CAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAyBhC,IAAM,iBAAA,GAAoB,CAAC,IAAA,EAAc,SAAA,KAAgC;AAC9E,EAAA,IAAI,cAAc,MAAA,EAAQ;AACxB,IAAA,OAAO,CAAA;AAAA;AAAA;;AAAA;AAAA,SAAA,EAKA,IAAI,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,EAqBb;AAEA,EAAA,OAAO,CAAA;AAAA;AAAA;;AAAA;AAAA,SAAA,EAKE,IAAI,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AAcf,CAAA;AAEO,IAAM,qBAAqB,MAAM,CAAA;AAAA,CAAA;AAGjC,IAAM,oBAAoB,MAAM,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAwBhC,IAAM,yBAAyB,MAAM,CAAA;AAAA,CAAA;AAGrC,IAAM,sBAAA,GAAyB,CAAC,IAAA,KAAiB,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAA,EAc/B,IAAI,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAUtB,IAAM,uBAAuB,MAAM,CAAA;AAAA;AAAA,CAAA;AAInC,IAAM,wBAAwB,MAAM,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAwBpC,IAAM,cAAA,GAAiB,CAAC,IAAA,EAAc,WAAA,KAAwB,KAAK,IAAI;;AAAA,EAE5E,WAAW;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA,EAkDX,IAAI,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA,CAAA;AA4DC,IAAM,uBAAuB,MAAM,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;;;AC9S1C,eAAeA,QAAO,IAAA,EAAgC;AACpD,EAAA,IAAI;AACF,IAAA,MAAMC,OAAO,IAAI,CAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,eAAsB,YAAY,OAAA,EAAqC;AACrE,EAAA,MAAM;AAAA,IACJ,IAAA;AAAA,IACA,WAAA,GAAc,CAAA,yCAAA,CAAA;AAAA,IACd,SAAA,GAAY;AAAA,GACd,GAAI,OAAA;AAEJ,EAAA,MAAM,UAAA,GAAaC,IAAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,IAAI,CAAA;AAG3C,EAAA,IAAI,MAAMF,OAAAA,CAAO,UAAU,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,WAAA,EAAc,IAAI,CAAA,gBAAA,CAAkB,CAAA;AAAA,EACtD;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,yBAAA,EAA8B,IAAI;AAAA,CAAI,CAAA;AAGlD,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,UAAA;AAAA,IACAE,IAAAA,CAAK,YAAY,KAAK,CAAA;AAAA,IACtBA,IAAAA,CAAK,UAAA,EAAY,KAAA,EAAO,OAAO,CAAA;AAAA,IAC/BA,IAAAA,CAAK,UAAA,EAAY,KAAA,EAAO,WAAW,CAAA;AAAA,IACnCA,IAAAA,CAAK,UAAA,EAAY,KAAA,EAAO,SAAS;AAAA,GACnC;AAEA,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAMC,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,IAAA,OAAA,CAAQ,GAAA,CAAI,cAAc,GAAA,CAAI,OAAA,CAAQ,QAAQ,GAAA,EAAI,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,EAC7D;AAGA,EAAA,MAAM,KAAA,GAAkD;AAAA,IACtD,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAS,mBAAA,CAAoB,IAAA,EAAM,WAAW,CAAA,EAAE;AAAA,IACxE,EAAE,IAAA,EAAM,eAAA,EAAiB,OAAA,EAAS,kBAAiB,EAAE;AAAA,IACrD,EAAE,IAAA,EAAM,YAAA,EAAc,OAAA,EAAS,mBAAkB,EAAE;AAAA,IACnD,EAAE,IAAA,EAAM,kBAAA,EAAoB,OAAA,EAAS,sBAAqB,EAAE;AAAA,IAC5D,EAAE,IAAA,EAAM,WAAA,EAAa,SAAS,cAAA,CAAe,IAAA,EAAM,WAAW,CAAA,EAAE;AAAA,IAChE,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAS,iBAAA,CAAkB,IAAA,EAAM,SAAS,CAAA,EAAE;AAAA,IACpE,EAAE,IAAA,EAAM,oBAAA,EAAsB,OAAA,EAAS,oBAAmB,EAAE;AAAA,IAC5D,EAAE,IAAA,EAAM,wBAAA,EAA0B,OAAA,EAAS,mBAAkB,EAAE;AAAA,IAC/D,EAAE,IAAA,EAAM,6BAAA,EAA+B,OAAA,EAAS,uBAAsB,EAAE;AAAA,IACxE,EAAE,IAAA,EAAM,wBAAA,EAA0B,OAAA,EAAS,wBAAuB,EAAE;AAAA,IACpE,EAAE,IAAA,EAAM,iCAAA,EAAmC,OAAA,EAAS,sBAAA,CAAuB,IAAI,CAAA,EAAE;AAAA,IACjF,EAAE,IAAA,EAAM,sBAAA,EAAwB,OAAA,EAAS,sBAAqB;AAAE,GAClE;AAEA,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,QAAA,GAAWD,IAAAA,CAAK,UAAA,EAAY,IAAA,CAAK,IAAI,CAAA;AAC3C,IAAA,MAAME,SAAAA,CAAU,QAAA,EAAU,IAAA,CAAK,OAAO,CAAA;AACtC,IAAA,OAAA,CAAQ,IAAI,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,IAAI,CAAA,CAAE,CAAA;AAAA,EACjD;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA;;AAAA;;AAAA,KAAA,EAKP,IAAI;AAAA;AAAA;;AAAA,EAIT,SAAA,KAAc,MAAA,GAAS,8CAAA,GAAiD,2BAA2B;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAQpG,CAAA;AACD;;;ACvGA,IAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAE5B,OAAA,CAAQ,KAAK,QAAQ,CAAA,CAAE,YAAY,8BAA8B,CAAA,CAAE,QAAQ,OAAO,CAAA;AAGlF,OAAA,CACG,OAAA,CAAQ,MAAM,CAAA,CACd,WAAA,CAAY,qCAAqC,CAAA,CACjD,QAAA,CAAS,QAAA,EAAU,cAAc,CAAA,CACjC,MAAA,CAAO,0BAAA,EAA4B,qBAAqB,EACxD,MAAA,CAAO,wBAAA,EAA0B,gCAAA,EAAkC,MAAM,CAAA,CACzE,MAAA,CAAO,gBAAA,EAAkB,kBAAkB,CAAA,CAC3C,MAAA,CAAO,OAAO,IAAA,EAAc,OAAA,KAAY;AACvC,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,CAAY;AAAA,MAChB,IAAA;AAAA,MACA,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,aAAa,OAAA,CAAQ;AAAA,KACtB,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM;AAAA,cAAA,EAAc,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,KAAK;AAAA,CAAI,CAAA;AAC9E,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAGH,OAAA,CACG,OAAA,CAAQ,WAAW,CAAA,CACnB,WAAA,CAAY,mBAAmB,CAAA,CAC/B,QAAA,CAAS,QAAA,EAAU,WAAW,CAAA,CAC9B,MAAA,CAAO,OAAO,IAAA,KAAiB;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,iBAAA,CAAkB,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA;AAAA,EAChD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM;AAAA,cAAA,EAAc,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,KAAK;AAAA,CAAI,CAAA;AAC9E,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAGH,OAAA,CACG,OAAA,CAAQ,eAAe,CAAA,CACvB,WAAA,CAAY,uBAAuB,CAAA,CACnC,QAAA,CAAS,QAAA,EAAU,eAAe,CAAA,CAClC,MAAA,CAAO,OAAO,IAAA,KAAiB;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,iBAAA,CAAkB,EAAE,IAAA,EAAM,UAAA,EAAY,MAAM,CAAA;AAAA,EACpD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM;AAAA,cAAA,EAAc,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,KAAK;AAAA,CAAI,CAAA;AAC9E,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAGH,OAAA,CACG,OAAA,CAAQ,aAAa,CAAA,CACrB,WAAA,CAAY,qBAAqB,CAAA,CACjC,QAAA,CAAS,QAAA,EAAU,aAAa,CAAA,CAChC,MAAA,CAAO,OAAO,IAAA,KAAiB;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,iBAAA,CAAkB,EAAE,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAAA,EAClD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM;AAAA,cAAA,EAAc,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,KAAK;AAAA,CAAI,CAAA;AAC9E,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAGH,OAAA,CAAQ,WAAA;AAAA,EACN,OAAA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQF,CAAA;AAGA,IAAI,OAAA,CAAQ,IAAA,CAAK,MAAA,IAAU,CAAA,EAAG;AAC5B,EAAA,MAAM,MAAA,GAAS,UAAA;AACf,EAAA,MAAM,IAAA,GAAO,UAAA;AACb,EAAA,MAAM,GAAA,GAAM,SAAA;AACZ,EAAA,MAAM,IAAA,GAAO,SAAA;AACb,EAAA,MAAM,KAAA,GAAQ,SAAA;AAEd,EAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,EACZ,GAAG,0CAA0C,KAAK;AAAA,EAClD,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,GAAA,EAAM,IAAI,GAAG,MAAM,CAAA,OAAA,EAAU,KAAK,CAAA,EAAA,EAAK,GAAG,CAAA,MAAA,EAAS,KAAK,CAAA,mBAAA,EAAsB,GAAG,IAAI,KAAK;AAAA,EACtG,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,OAAA,EAAU,IAAI,gBAAgB,KAAK,CAAA,iBAAA,EAAoB,GAAG,CAAA,CAAA,EAAI,KAAK;AAAA,EAC/E,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,qCAAA,EAAwC,GAAG,IAAI,KAAK;AAAA,EAChE,GAAG,0CAA0C,KAAK;AAAA,CACnD,CAAA;AACD,CAAA,MAAO;AACL,EAAA,OAAA,CAAQ,KAAA,EAAM;AAChB","file":"index.js","sourcesContent":["import { mkdir, writeFile, access, readFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\n\nexport type ComponentType = 'tool' | 'resource' | 'prompt';\n\nexport interface GenerateOptions {\n type: ComponentType;\n name: string;\n}\n\n/**\n * Convert a name to PascalCase\n */\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert a name to kebab-case\n */\nfunction toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Check if a file exists\n */\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate tool template\n */\nfunction toolTemplate(className: string, toolName: string): string {\n return `import { BaseTool } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\n/**\n * ${className} - Description of what this tool does\n */\nexport class ${className} extends BaseTool {\n name = '${toolName}';\n description = 'TODO: Add description';\n\n schema = z.object({\n // TODO: Define your input schema\n input: z.string().describe('Input parameter'),\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n // TODO: Implement your tool logic\n return {\n content: {\n result: \\`Processed: \\${input.input}\\`,\n },\n };\n }\n}\n`;\n}\n\n/**\n * Generate tool test template\n */\nfunction toolTestTemplate(className: string, toolName: string): string {\n return `import { describe, it, expect } from 'vitest';\nimport { createTestClient } from '@eaperezc/mcpgen/testing';\nimport { ${className} } from './${className}.js';\n\ndescribe('${className}', () => {\n it('should execute successfully', async () => {\n const client = createTestClient();\n client.registerTool(new ${className}());\n\n const result = await client.callTool('${toolName}', { input: 'test' });\n\n expect(result.content).toHaveProperty('result');\n });\n\n it('should require input parameter', async () => {\n const client = createTestClient();\n client.registerTool(new ${className}());\n\n await expect(client.callTool('${toolName}', {})).rejects.toThrow();\n });\n});\n`;\n}\n\n/**\n * Generate resource template\n */\nfunction resourceTemplate(className: string, resourceName: string): string {\n return `import { BaseResource } from '@eaperezc/mcpgen';\n\n/**\n * ${className} - Description of what this resource provides\n */\nexport class ${className} extends BaseResource {\n uri = '${resourceName}://data';\n name = '${className}';\n description = 'TODO: Add description';\n\n async read() {\n // TODO: Implement your resource logic\n return {\n contents: [\n this.json({\n // Your data here\n example: 'data',\n }),\n ],\n };\n }\n}\n`;\n}\n\n/**\n * Generate prompt template\n */\nfunction promptTemplate(className: string, promptName: string): string {\n return `import { BasePrompt } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\n/**\n * ${className} - Description of what this prompt does\n */\nexport class ${className} extends BasePrompt {\n name = '${promptName}';\n description = 'TODO: Add description';\n\n arguments = z.object({\n // TODO: Define your arguments schema\n topic: z.string().describe('The topic to discuss'),\n });\n\n async render(args: z.infer<typeof this.arguments>) {\n // TODO: Implement your prompt logic\n return {\n messages: [\n this.user(\\`Please help me with: \\${args.topic}\\`),\n ],\n };\n }\n}\n`;\n}\n\n/**\n * Update index file to export the new component\n */\nasync function updateIndexFile(indexPath: string, className: string, fileName: string): Promise<void> {\n let content = '';\n\n if (await exists(indexPath)) {\n content = await readFile(indexPath, 'utf-8');\n }\n\n const exportLine = `export { ${className} } from './${fileName}.js';`;\n\n if (!content.includes(exportLine)) {\n // Remove comments and empty lines at the start for clean exports\n const lines = content.split('\\n').filter(line =>\n line.trim() && !line.trim().startsWith('//')\n );\n lines.push(exportLine);\n content = lines.join('\\n') + '\\n';\n await writeFile(indexPath, content);\n }\n}\n\n/**\n * Generate a new component\n */\nexport async function generateComponent(options: GenerateOptions): Promise<void> {\n const { type, name } = options;\n\n const className = toPascalCase(name) + (type === 'tool' ? 'Tool' : type === 'resource' ? 'Resource' : 'Prompt');\n const fileName = className;\n const kebabName = toKebabCase(name);\n\n // Determine directory\n const typeDir = type === 'tool' ? 'tools' : type === 'resource' ? 'resources' : 'prompts';\n const srcDir = join(process.cwd(), 'src', typeDir);\n const filePath = join(srcDir, `${fileName}.ts`);\n const testFilePath = join(srcDir, `${fileName}.test.ts`);\n const indexPath = join(srcDir, 'index.ts');\n\n // Check if src directory exists (are we in an mcpgen project?)\n if (!(await exists(join(process.cwd(), 'src')))) {\n throw new Error('No src/ directory found. Are you in an mcpgen project? Run \"mcpgen init\" first.');\n }\n\n // Create directory if it doesn't exist\n await mkdir(srcDir, { recursive: true });\n\n // Check if file already exists\n if (await exists(filePath)) {\n throw new Error(`${type} '${fileName}' already exists at ${filePath}`);\n }\n\n // Generate content based on type\n let content: string;\n let testContent: string | null = null;\n switch (type) {\n case 'tool':\n content = toolTemplate(className, kebabName);\n testContent = toolTestTemplate(className, kebabName);\n break;\n case 'resource':\n content = resourceTemplate(className, kebabName);\n break;\n case 'prompt':\n content = promptTemplate(className, kebabName);\n break;\n default:\n throw new Error(`Unknown component type: ${type}`);\n }\n\n // Write file\n await writeFile(filePath, content);\n console.log(`\\n✅ Created ${type}: ${filePath.replace(process.cwd(), '.')}`);\n\n // Write test file for tools\n if (testContent) {\n await writeFile(testFilePath, testContent);\n console.log(` Created test: ${testFilePath.replace(process.cwd(), '.')}`);\n }\n\n // Update index file\n await updateIndexFile(indexPath, className, fileName);\n console.log(` Updated: ${indexPath.replace(process.cwd(), '.')}`);\n\n console.log(`\nNext steps:\n\n 1. Edit src/${typeDir}/${fileName}.ts to implement your ${type}\n 2. Register it in src/index.ts:\n\n import { ${className} } from './${typeDir}/${fileName}.js';\n server.${type}(new ${className}());\n 3. Run tests: npm test\n`);\n}\n","/**\n * Templates for CLI scaffolding\n */\n\nexport const packageJsonTemplate = (name: string, description: string) => `{\n \"name\": \"${name}\",\n \"version\": \"0.1.0\",\n \"description\": \"${description}\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"dev\": \"tsx watch src/index.ts\",\n \"start\": \"node dist/index.js\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src\",\n \"typecheck\": \"tsc --noEmit\",\n \"inspector\": \"npx @modelcontextprotocol/inspector\"\n },\n \"keywords\": [\"mcp\", \"model-context-protocol\"],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@eaperezc/mcpgen\": \"^0.1.0\",\n \"@modelcontextprotocol/sdk\": \"^1.11.0\",\n \"zod\": \"^3.23.8\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.10.0\",\n \"typescript\": \"^5.7.2\",\n \"tsx\": \"^4.19.2\",\n \"vitest\": \"^2.1.8\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n`;\n\nexport const tsconfigTemplate = () => `{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"lib\": [\"ES2022\"],\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"declaration\": true,\n \"outDir\": \"./dist\",\n \"rootDir\": \"./src\",\n \"resolveJsonModule\": true\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\", \"dist\"]\n}\n`;\n\nexport const gitignoreTemplate = () => `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n\n# Environment files\n.env\n.env.local\n.env.*.local\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\n`;\n\nexport const mainIndexTemplate = (name: string, transport: 'stdio' | 'http') => {\n if (transport === 'http') {\n return `import { McpServer } from '@eaperezc/mcpgen';\nimport { GreetTool } from './tools/GreetTool.js';\nimport { ConfigResource } from './resources/ConfigResource.js';\n\nconst server = new McpServer({\n name: '${name}',\n version: '0.1.0',\n transport: {\n type: 'http',\n port: 3000,\n cors: { origin: '*' },\n },\n logging: { level: 'info' },\n});\n\n// Register tools\nserver.tool(new GreetTool());\n\n// Register resources\nserver.resource(new ConfigResource());\n\n// Start the server\nserver.start().then(() => {\n console.log('MCP server running at http://localhost:3000/mcp');\n});\n`;\n }\n\n return `import { McpServer } from '@eaperezc/mcpgen';\nimport { GreetTool } from './tools/GreetTool.js';\nimport { ConfigResource } from './resources/ConfigResource.js';\n\nconst server = new McpServer({\n name: '${name}',\n version: '0.1.0',\n logging: { level: 'info' },\n});\n\n// Register tools\nserver.tool(new GreetTool());\n\n// Register resources\nserver.resource(new ConfigResource());\n\n// Start the server\nserver.start();\n`;\n};\n\nexport const toolsIndexTemplate = () => `export { GreetTool } from './GreetTool.js';\n`;\n\nexport const greetToolTemplate = () => `import { BaseTool } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\n/**\n * Example tool that greets a user\n */\nexport class GreetTool extends BaseTool {\n name = 'greet';\n description = 'Greets a user by name';\n\n schema = z.object({\n name: z.string().describe('The name of the person to greet'),\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n return {\n content: {\n greeting: \\`Hello, \\${input.name}! Welcome to your MCP server.\\`,\n },\n };\n }\n}\n`;\n\nexport const resourcesIndexTemplate = () => `export { ConfigResource } from './ConfigResource.js';\n`;\n\nexport const configResourceTemplate = (name: string) => `import { BaseResource } from '@eaperezc/mcpgen';\n\n/**\n * Example resource that provides server configuration\n */\nexport class ConfigResource extends BaseResource {\n uri = 'config://server';\n name = 'Server Configuration';\n description = 'Provides server configuration information';\n\n async read() {\n return {\n contents: [\n this.json({\n serverName: '${name}',\n version: '0.1.0',\n environment: process.env.NODE_ENV ?? 'development',\n }),\n ],\n };\n }\n}\n`;\n\nexport const promptsIndexTemplate = () => `// Export your prompts here\n// export { SummarizePrompt } from './SummarizePrompt.js';\n`;\n\nexport const greetToolTestTemplate = () => `import { describe, it, expect } from 'vitest';\nimport { createTestClient } from '@eaperezc/mcpgen/testing';\nimport { GreetTool } from './GreetTool.js';\n\ndescribe('GreetTool', () => {\n it('should greet the user', async () => {\n const client = createTestClient();\n client.registerTool(new GreetTool());\n\n const result = await client.callTool('greet', { name: 'Alice' });\n\n expect(result.content).toHaveProperty('greeting');\n expect((result.content as { greeting: string }).greeting).toContain('Alice');\n });\n\n it('should require a name', async () => {\n const client = createTestClient();\n client.registerTool(new GreetTool());\n\n await expect(client.callTool('greet', {})).rejects.toThrow();\n });\n});\n`;\n\nexport const readmeTemplate = (name: string, description: string) => `# ${name}\n\n${description}\n\n## Getting Started\n\n### Installation\n\n\\`\\`\\`bash\nnpm install\n\\`\\`\\`\n\n### Development\n\nRun the server in development mode with hot reload:\n\n\\`\\`\\`bash\nnpm run dev\n\\`\\`\\`\n\n### Production\n\nBuild and run:\n\n\\`\\`\\`bash\nnpm run build\nnpm start\n\\`\\`\\`\n\n### Testing\n\n\\`\\`\\`bash\nnpm test\n\\`\\`\\`\n\n### MCP Inspector\n\nTo test and debug your server with the MCP Inspector:\n\n\\`\\`\\`bash\n# Terminal 1: Start the server\nnpm run dev\n\n# Terminal 2: Launch the inspector\nnpm run inspector\n\\`\\`\\`\n\nThen connect to \\`http://localhost:3000/mcp\\` using **Streamable HTTP** transport.\n\n## Project Structure\n\n\\`\\`\\`\n${name}/\n├── src/\n│ ├── tools/ # MCP tools\n│ │ ├── GreetTool.ts\n│ │ └── GreetTool.test.ts\n│ ├── resources/ # MCP resources\n│ │ └── ConfigResource.ts\n│ ├── prompts/ # MCP prompts\n│ └── index.ts # Server entry point\n├── package.json\n└── tsconfig.json\n\\`\\`\\`\n\n## Adding New Components\n\n### Tools\n\nCreate a new file in \\`src/tools/\\`:\n\n\\`\\`\\`typescript\nimport { BaseTool } from '@eaperezc/mcpgen';\nimport { z } from 'zod';\n\nexport class MyTool extends BaseTool {\n name = 'my-tool';\n description = 'Description of what this tool does';\n\n schema = z.object({\n // Define your input schema\n });\n\n async execute(input: z.infer<typeof this.schema>) {\n // Implement your tool logic\n return { content: { result: 'success' } };\n }\n}\n\\`\\`\\`\n\n### Resources\n\nCreate a new file in \\`src/resources/\\`:\n\n\\`\\`\\`typescript\nimport { BaseResource } from '@eaperezc/mcpgen';\n\nexport class MyResource extends BaseResource {\n uri = 'my-resource://example';\n name = 'My Resource';\n\n async read() {\n return { contents: [this.json({ data: 'example' })] };\n }\n}\n\\`\\`\\`\n\n## License\n\nMIT\n`;\n\nexport const vitestConfigTemplate = () => `import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environment: 'node',\n },\n});\n`;\n","import { mkdir, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n packageJsonTemplate,\n tsconfigTemplate,\n gitignoreTemplate,\n mainIndexTemplate,\n toolsIndexTemplate,\n greetToolTemplate,\n greetToolTestTemplate,\n resourcesIndexTemplate,\n configResourceTemplate,\n promptsIndexTemplate,\n readmeTemplate,\n vitestConfigTemplate,\n} from '../templates/index.js';\n\nexport interface InitOptions {\n name: string;\n description?: string;\n transport?: 'stdio' | 'http';\n skipInstall?: boolean;\n}\n\n/**\n * Check if a directory exists\n */\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Initialize a new MCP server project\n */\nexport async function initProject(options: InitOptions): Promise<void> {\n const {\n name,\n description = `An MCP server built with @eaperezc/mcpgen`,\n transport = 'http',\n } = options;\n\n const projectDir = join(process.cwd(), name);\n\n // Check if directory already exists\n if (await exists(projectDir)) {\n throw new Error(`Directory '${name}' already exists`);\n }\n\n console.log(`\\nCreating new MCP server: ${name}\\n`);\n\n // Create directories\n const dirs = [\n projectDir,\n join(projectDir, 'src'),\n join(projectDir, 'src', 'tools'),\n join(projectDir, 'src', 'resources'),\n join(projectDir, 'src', 'prompts'),\n ];\n\n for (const dir of dirs) {\n await mkdir(dir, { recursive: true });\n console.log(` Created: ${dir.replace(process.cwd(), '.')}`);\n }\n\n // Create files\n const files: Array<{ path: string; content: string }> = [\n { path: 'package.json', content: packageJsonTemplate(name, description) },\n { path: 'tsconfig.json', content: tsconfigTemplate() },\n { path: '.gitignore', content: gitignoreTemplate() },\n { path: 'vitest.config.ts', content: vitestConfigTemplate() },\n { path: 'README.md', content: readmeTemplate(name, description) },\n { path: 'src/index.ts', content: mainIndexTemplate(name, transport) },\n { path: 'src/tools/index.ts', content: toolsIndexTemplate() },\n { path: 'src/tools/GreetTool.ts', content: greetToolTemplate() },\n { path: 'src/tools/GreetTool.test.ts', content: greetToolTestTemplate() },\n { path: 'src/resources/index.ts', content: resourcesIndexTemplate() },\n { path: 'src/resources/ConfigResource.ts', content: configResourceTemplate(name) },\n { path: 'src/prompts/index.ts', content: promptsIndexTemplate() },\n ];\n\n for (const file of files) {\n const filePath = join(projectDir, file.path);\n await writeFile(filePath, file.content);\n console.log(` Created: ./${name}/${file.path}`);\n }\n\n console.log(`\n✅ Project created successfully!\n\nNext steps:\n\n cd ${name}\n npm install\n npm run dev\n\n${transport === 'http' ? 'Server will run at http://localhost:3000/mcp' : 'Server will run via stdio'}\n\nTo add new components:\n - Tools: Create files in src/tools/\n - Resources: Create files in src/resources/\n - Prompts: Create files in src/prompts/\n\nHappy building! 🚀\n`);\n}\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { generateComponent } from './commands/generate.js';\nimport { initProject } from './commands/init.js';\n\nconst program = new Command();\n\nprogram.name('mcpgen').description('CLI for building MCP servers').version('0.1.0');\n\n// Init command\nprogram\n .command('init')\n .description('Initialize a new MCP server project')\n .argument('<name>', 'Project name')\n .option('-d, --description <desc>', 'Project description')\n .option('-t, --transport <type>', 'Transport type (http or stdio)', 'http')\n .option('--skip-install', 'Skip npm install')\n .action(async (name: string, options) => {\n try {\n await initProject({\n name,\n description: options.description,\n transport: options.transport as 'stdio' | 'http',\n skipInstall: options.skipInstall,\n });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:tool command\nprogram\n .command('make:tool')\n .description('Create a new tool')\n .argument('<name>', 'Tool name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'tool', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:resource command\nprogram\n .command('make:resource')\n .description('Create a new resource')\n .argument('<name>', 'Resource name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'resource', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// make:prompt command\nprogram\n .command('make:prompt')\n .description('Create a new prompt')\n .argument('<name>', 'Prompt name')\n .action(async (name: string) => {\n try {\n await generateComponent({ type: 'prompt', name });\n } catch (error) {\n console.error(`\\n❌ Error: ${error instanceof Error ? error.message : error}\\n`);\n process.exit(1);\n }\n });\n\n// Add examples to help\nprogram.addHelpText(\n 'after',\n `\nExamples:\n $ mcpgen init my-mcp-server Create a new MCP server (HTTP)\n $ mcpgen init my-api --transport stdio Create with stdio transport\n $ mcpgen make:tool search Create a new tool\n $ mcpgen make:resource database Create a new resource\n $ mcpgen make:prompt summarize Create a new prompt\n`\n);\n\n// Show welcome message if no arguments provided\nif (process.argv.length <= 2) {\n const yellow = '\\x1b[33m';\n const cyan = '\\x1b[36m';\n const dim = '\\x1b[2m';\n const bold = '\\x1b[1m';\n const reset = '\\x1b[0m';\n\n console.log(`\n${dim}+-------------------------------------+${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} ${bold}${yellow}MCP-GEN${reset} ${dim}v0.1.0${reset} ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} A TypeScript framework for ${dim}|${reset}\n${dim}|${reset} building MCP servers ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}|${reset} Run ${cyan}mcpgen --help${reset} for commands ${dim}|${reset}\n${dim}|${reset} ${dim}|${reset}\n${dim}+-------------------------------------+${reset}\n`);\n} else {\n program.parse();\n}\n"]}
package/dist/index.cjs CHANGED
@@ -879,8 +879,9 @@ var HttpTransport = class {
879
879
  config;
880
880
  logger;
881
881
  httpServer = null;
882
- mcpTransport = null;
883
882
  running = false;
883
+ serverFactory = null;
884
+ sessions = /* @__PURE__ */ new Map();
884
885
  constructor(config, logger2) {
885
886
  this.config = {
886
887
  ...config,
@@ -892,17 +893,13 @@ var HttpTransport = class {
892
893
  }
893
894
  /**
894
895
  * Start the HTTP transport
896
+ * @param serverFactory - Factory function to create new Server instances per session
895
897
  */
896
- async start(mcpServer) {
898
+ async start(serverFactory) {
897
899
  if (this.running) {
898
900
  throw new Error("Transport is already running");
899
901
  }
900
- this.mcpTransport = new streamableHttp_js.StreamableHTTPServerTransport({
901
- sessionIdGenerator: () => crypto.randomUUID()
902
- });
903
- if (mcpServer) {
904
- await mcpServer.connect(this.mcpTransport);
905
- }
902
+ this.serverFactory = serverFactory ?? null;
906
903
  this.httpServer = http.createServer((req, res) => {
907
904
  this.handleRequest(req, res);
908
905
  });
@@ -930,10 +927,15 @@ var HttpTransport = class {
930
927
  if (!this.running) {
931
928
  return;
932
929
  }
933
- if (this.mcpTransport) {
934
- await this.mcpTransport.close();
935
- this.mcpTransport = null;
930
+ for (const [sessionId, session] of this.sessions) {
931
+ try {
932
+ await session.transport.close();
933
+ await session.server.close();
934
+ } catch (error) {
935
+ this.logger.error(`Error closing session ${sessionId}`, error instanceof Error ? error : void 0);
936
+ }
936
937
  }
938
+ this.sessions.clear();
937
939
  if (this.httpServer) {
938
940
  return new Promise((resolve, reject) => {
939
941
  this.httpServer.close((error) => {
@@ -957,10 +959,34 @@ var HttpTransport = class {
957
959
  return this.running;
958
960
  }
959
961
  /**
960
- * Get the underlying MCP transport (for advanced use cases)
962
+ * Get all active sessions (for debugging/monitoring)
963
+ */
964
+ getActiveSessions() {
965
+ return Array.from(this.sessions.keys());
966
+ }
967
+ /**
968
+ * Get or create a session for the given session ID
961
969
  */
962
- getMcpTransport() {
963
- return this.mcpTransport;
970
+ async getOrCreateSession(sessionId) {
971
+ let session = this.sessions.get(sessionId);
972
+ if (!session) {
973
+ if (!this.serverFactory) {
974
+ throw new Error("No server factory configured");
975
+ }
976
+ const transport = new streamableHttp_js.StreamableHTTPServerTransport({
977
+ sessionIdGenerator: () => sessionId
978
+ });
979
+ const server = this.serverFactory();
980
+ await server.connect(transport);
981
+ session = {
982
+ transport,
983
+ server,
984
+ createdAt: Date.now()
985
+ };
986
+ this.sessions.set(sessionId, session);
987
+ this.logger.debug("Created new session", { sessionId });
988
+ }
989
+ return session;
964
990
  }
965
991
  /**
966
992
  * Handle incoming HTTP request
@@ -981,9 +1007,9 @@ var HttpTransport = class {
981
1007
  return;
982
1008
  }
983
1009
  if (path === this.config.basePath || path === `${this.config.basePath}/`) {
984
- if (!this.mcpTransport) {
1010
+ if (!this.serverFactory) {
985
1011
  res.writeHead(503, { "Content-Type": "application/json" });
986
- res.end(JSON.stringify({ error: "Transport not initialized" }));
1012
+ res.end(JSON.stringify({ error: "Server factory not configured" }));
987
1013
  return;
988
1014
  }
989
1015
  try {
@@ -991,7 +1017,12 @@ var HttpTransport = class {
991
1017
  if (req.method === "POST") {
992
1018
  body = await this.parseBody(req);
993
1019
  }
994
- await this.mcpTransport.handleRequest(req, res, body);
1020
+ let sessionId = req.headers["mcp-session-id"];
1021
+ if (!sessionId) {
1022
+ sessionId = crypto.randomUUID();
1023
+ }
1024
+ const session = await this.getOrCreateSession(sessionId);
1025
+ await session.transport.handleRequest(req, res, body);
995
1026
  } catch (error) {
996
1027
  this.logger.error("Error handling MCP request", error instanceof Error ? error : void 0);
997
1028
  if (!res.headersSent) {
@@ -1108,10 +1139,17 @@ var McpServer = class {
1108
1139
  };
1109
1140
  }
1110
1141
  /**
1111
- * Set up MCP request handlers
1142
+ * Set up MCP request handlers on a server instance
1112
1143
  */
1113
1144
  setupHandlers() {
1114
- this.server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
1145
+ this.setupHandlersOnServer(this.server);
1146
+ }
1147
+ /**
1148
+ * Configure handlers on a given Server instance
1149
+ * This is used both for the main server (stdio) and for per-session servers (http)
1150
+ */
1151
+ setupHandlersOnServer(server) {
1152
+ server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
1115
1153
  return runInRequestContextAsync(async () => {
1116
1154
  const tools = this.toolRegistry.getAll();
1117
1155
  return {
@@ -1123,7 +1161,7 @@ var McpServer = class {
1123
1161
  };
1124
1162
  });
1125
1163
  });
1126
- this.server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
1164
+ server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
1127
1165
  return runInRequestContextAsync(async () => {
1128
1166
  const { name, arguments: args } = request.params;
1129
1167
  const tool = this.toolRegistry.get(name);
@@ -1142,7 +1180,7 @@ var McpServer = class {
1142
1180
  };
1143
1181
  });
1144
1182
  });
1145
- this.server.setRequestHandler(types_js.ListResourcesRequestSchema, async () => {
1183
+ server.setRequestHandler(types_js.ListResourcesRequestSchema, async () => {
1146
1184
  return runInRequestContextAsync(async () => {
1147
1185
  const resources = this.resourceRegistry.getAll();
1148
1186
  return {
@@ -1155,7 +1193,7 @@ var McpServer = class {
1155
1193
  };
1156
1194
  });
1157
1195
  });
1158
- this.server.setRequestHandler(types_js.ReadResourceRequestSchema, async (request) => {
1196
+ server.setRequestHandler(types_js.ReadResourceRequestSchema, async (request) => {
1159
1197
  return runInRequestContextAsync(async () => {
1160
1198
  const { uri } = request.params;
1161
1199
  const resource = this.resourceRegistry.get(uri);
@@ -1171,7 +1209,7 @@ var McpServer = class {
1171
1209
  };
1172
1210
  });
1173
1211
  });
1174
- this.server.setRequestHandler(types_js.ListPromptsRequestSchema, async () => {
1212
+ server.setRequestHandler(types_js.ListPromptsRequestSchema, async () => {
1175
1213
  return runInRequestContextAsync(async () => {
1176
1214
  const prompts = this.promptRegistry.getAll();
1177
1215
  return {
@@ -1190,7 +1228,7 @@ var McpServer = class {
1190
1228
  };
1191
1229
  });
1192
1230
  });
1193
- this.server.setRequestHandler(types_js.GetPromptRequestSchema, async (request) => {
1231
+ server.setRequestHandler(types_js.GetPromptRequestSchema, async (request) => {
1194
1232
  return runInRequestContextAsync(async () => {
1195
1233
  const { name, arguments: args } = request.params;
1196
1234
  const prompt = this.promptRegistry.get(name);
@@ -1208,6 +1246,24 @@ var McpServer = class {
1208
1246
  });
1209
1247
  });
1210
1248
  }
1249
+ /**
1250
+ * Create a server factory for HTTP transport (creates per-session servers)
1251
+ */
1252
+ createServerFactory() {
1253
+ return () => {
1254
+ const server = new index_js.Server(
1255
+ {
1256
+ name: this.config.name,
1257
+ version: this.config.version
1258
+ },
1259
+ {
1260
+ capabilities: this.getCapabilities()
1261
+ }
1262
+ );
1263
+ this.setupHandlersOnServer(server);
1264
+ return server;
1265
+ };
1266
+ }
1211
1267
  tool(toolOrName, definition) {
1212
1268
  if (typeof toolOrName === "string" && definition) {
1213
1269
  this.toolRegistry.registerInline(toolOrName, definition);
@@ -1251,14 +1307,6 @@ var McpServer = class {
1251
1307
  }
1252
1308
  const transportConfig = this.config.transport ?? "stdio";
1253
1309
  const transportType = typeof transportConfig === "string" ? transportConfig : transportConfig.type;
1254
- this.logger.info("Starting MCP server", {
1255
- name: this.config.name,
1256
- version: this.config.version,
1257
- transport: transportType,
1258
- tools: this.toolRegistry.size,
1259
- resources: this.resourceRegistry.size,
1260
- prompts: this.promptRegistry.size
1261
- });
1262
1310
  try {
1263
1311
  await this.hooks.onBeforeStart?.();
1264
1312
  if (transportType === "stdio") {
@@ -1267,7 +1315,7 @@ var McpServer = class {
1267
1315
  } else if (transportType === "http") {
1268
1316
  const httpConfig = transportConfig;
1269
1317
  this.httpTransport = new HttpTransport(httpConfig, this.logger);
1270
- await this.httpTransport.start(this.server);
1318
+ await this.httpTransport.start(this.createServerFactory());
1271
1319
  } else if (transportType === "sse") {
1272
1320
  throw new McpError({
1273
1321
  code: "NOT_IMPLEMENTED" /* NOT_IMPLEMENTED */,
@@ -1276,8 +1324,12 @@ var McpServer = class {
1276
1324
  }
1277
1325
  this.running = true;
1278
1326
  await this.hooks.onAfterStart?.();
1279
- this.logger.info("MCP server started successfully", {
1327
+ this.logger.info("MCP server started", {
1328
+ version: this.config.version,
1280
1329
  transport: transportType,
1330
+ tools: this.toolRegistry.size,
1331
+ resources: this.resourceRegistry.size,
1332
+ prompts: this.promptRegistry.size,
1281
1333
  ...transportType === "http" && {
1282
1334
  port: transportConfig.port,
1283
1335
  host: transportConfig.host ?? "0.0.0.0"