@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/README.md +31 -27
- package/dist/cli/index.cjs +70 -24
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +70 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +86 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -22
- package/dist/index.d.ts +14 -22
- package/dist/index.js +86 -34
- package/dist/index.js.map +1 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/{types-B9yzEar_.d.cts → types-Bu1xVhfb.d.cts} +10 -1
- package/dist/{types-B9yzEar_.d.ts → types-Bu1xVhfb.d.ts} +10 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @eaperezc/mcpgen
|
|
2
2
|
|
|
3
3
|
A TypeScript framework for building MCP (Model Context Protocol) servers with excellent developer experience.
|
|
4
4
|
|
|
@@ -9,14 +9,14 @@ A TypeScript framework for building MCP (Model Context Protocol) servers with ex
|
|
|
9
9
|
- **Built-in Testing** - In-memory test client for unit testing your MCP servers
|
|
10
10
|
- **Structured Logging** - Pino-based logging with correlation IDs
|
|
11
11
|
- **Type-safe** - Full TypeScript support with Zod schema validation
|
|
12
|
-
- **Production Ready** - Supports
|
|
12
|
+
- **Production Ready** - Supports HTTP and stdio transports
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install
|
|
17
|
+
npm install @eaperezc/mcpgen @modelcontextprotocol/sdk
|
|
18
18
|
# or
|
|
19
|
-
pnpm add
|
|
19
|
+
pnpm add @eaperezc/mcpgen @modelcontextprotocol/sdk
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
## CLI - Scaffold New Projects
|
|
@@ -25,13 +25,13 @@ The fastest way to get started is using the CLI:
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
# Install globally
|
|
28
|
-
npm install -g
|
|
28
|
+
npm install -g @eaperezc/mcpgen
|
|
29
29
|
|
|
30
|
-
# Create a new project
|
|
31
|
-
|
|
30
|
+
# Create a new project (HTTP by default)
|
|
31
|
+
mcpgen init my-mcp-server
|
|
32
32
|
|
|
33
|
-
# Create with
|
|
34
|
-
|
|
33
|
+
# Create with stdio transport
|
|
34
|
+
mcpgen init my-api --transport stdio
|
|
35
35
|
|
|
36
36
|
# Navigate and start
|
|
37
37
|
cd my-mcp-server
|
|
@@ -43,31 +43,31 @@ npm run dev
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
# Generate a new tool
|
|
46
|
-
|
|
46
|
+
mcpgen make:tool search-users
|
|
47
47
|
|
|
48
48
|
# Generate a new resource
|
|
49
|
-
|
|
49
|
+
mcpgen make:resource database
|
|
50
50
|
|
|
51
51
|
# Generate a new prompt
|
|
52
|
-
|
|
52
|
+
mcpgen make:prompt summarize
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
### CLI Commands
|
|
56
56
|
|
|
57
57
|
| Command | Description |
|
|
58
58
|
|---------|-------------|
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
59
|
+
| `mcpgen init <name>` | Create a new MCP server project (HTTP) |
|
|
60
|
+
| `mcpgen init <name> --transport stdio` | Create with stdio transport |
|
|
61
|
+
| `mcpgen make:tool <name>` | Generate a new tool |
|
|
62
|
+
| `mcpgen make:resource <name>` | Generate a new resource |
|
|
63
|
+
| `mcpgen make:prompt <name>` | Generate a new prompt |
|
|
64
64
|
|
|
65
65
|
## Quick Start
|
|
66
66
|
|
|
67
67
|
### Class-based API (Recommended)
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
|
-
import { McpServer, BaseTool, BaseResource } from '
|
|
70
|
+
import { McpServer, BaseTool, BaseResource } from '@eaperezc/mcpgen';
|
|
71
71
|
import { z } from 'zod';
|
|
72
72
|
|
|
73
73
|
// Define a tool
|
|
@@ -98,6 +98,10 @@ class ConfigResource extends BaseResource {
|
|
|
98
98
|
const server = new McpServer({
|
|
99
99
|
name: 'my-server',
|
|
100
100
|
version: '1.0.0',
|
|
101
|
+
transport: {
|
|
102
|
+
type: 'http',
|
|
103
|
+
port: 3000,
|
|
104
|
+
},
|
|
101
105
|
});
|
|
102
106
|
|
|
103
107
|
server.tool(new GreetTool());
|
|
@@ -108,7 +112,7 @@ server.start();
|
|
|
108
112
|
### Fluent Builder API
|
|
109
113
|
|
|
110
114
|
```typescript
|
|
111
|
-
import { createServer } from '
|
|
115
|
+
import { createServer } from '@eaperezc/mcpgen';
|
|
112
116
|
import { z } from 'zod';
|
|
113
117
|
|
|
114
118
|
const server = createServer({ name: 'my-server', version: '1.0.0' })
|
|
@@ -128,11 +132,11 @@ await server.start();
|
|
|
128
132
|
|
|
129
133
|
## Testing
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
mcpgen includes a built-in test client for unit testing your MCP servers:
|
|
132
136
|
|
|
133
137
|
```typescript
|
|
134
138
|
import { describe, it, expect } from 'vitest';
|
|
135
|
-
import { createTestClient } from '
|
|
139
|
+
import { createTestClient } from '@eaperezc/mcpgen/testing';
|
|
136
140
|
import { GreetTool } from './tools/GreetTool';
|
|
137
141
|
|
|
138
142
|
describe('GreetTool', () => {
|
|
@@ -156,8 +160,8 @@ describe('GreetTool', () => {
|
|
|
156
160
|
### Testing with Server Builder
|
|
157
161
|
|
|
158
162
|
```typescript
|
|
159
|
-
import { TestClient } from '
|
|
160
|
-
import { createServer } from '
|
|
163
|
+
import { TestClient } from '@eaperezc/mcpgen/testing';
|
|
164
|
+
import { createServer } from '@eaperezc/mcpgen';
|
|
161
165
|
|
|
162
166
|
const server = createServer({ name: 'test', version: '1.0.0' })
|
|
163
167
|
.tool('add', {
|
|
@@ -241,7 +245,7 @@ abstract class BasePrompt<TArgs extends z.ZodType> {
|
|
|
241
245
|
|
|
242
246
|
## Project Structure
|
|
243
247
|
|
|
244
|
-
When building MCP servers with
|
|
248
|
+
When building MCP servers with mcpgen, we recommend:
|
|
245
249
|
|
|
246
250
|
```
|
|
247
251
|
my-mcp-server/
|
|
@@ -263,10 +267,10 @@ my-mcp-server/
|
|
|
263
267
|
|
|
264
268
|
## HTTP Transport
|
|
265
269
|
|
|
266
|
-
|
|
270
|
+
mcpgen uses HTTP transport by default:
|
|
267
271
|
|
|
268
272
|
```typescript
|
|
269
|
-
import { McpServer } from '
|
|
273
|
+
import { McpServer } from '@eaperezc/mcpgen';
|
|
270
274
|
|
|
271
275
|
const server = new McpServer({
|
|
272
276
|
name: 'my-http-server',
|
|
@@ -316,7 +320,7 @@ await server.start();
|
|
|
316
320
|
- [x] HTTP transport (production-ready)
|
|
317
321
|
- [x] Testing utilities
|
|
318
322
|
- [x] Structured logging
|
|
319
|
-
- [x] CLI scaffolding (`
|
|
323
|
+
- [x] CLI scaffolding (`mcpgen init`, `mcpgen make:*`)
|
|
320
324
|
- [ ] SSE transport
|
|
321
325
|
- [ ] OAuth 2.1 authentication
|
|
322
326
|
- [ ] API key authentication
|
package/dist/cli/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@ async function exists(path) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
function toolTemplate(className, toolName) {
|
|
23
|
-
return `import { BaseTool } from '
|
|
23
|
+
return `import { BaseTool } from '@eaperezc/mcpgen';
|
|
24
24
|
import { z } from 'zod';
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -46,8 +46,32 @@ export class ${className} extends BaseTool {
|
|
|
46
46
|
}
|
|
47
47
|
`;
|
|
48
48
|
}
|
|
49
|
+
function toolTestTemplate(className, toolName) {
|
|
50
|
+
return `import { describe, it, expect } from 'vitest';
|
|
51
|
+
import { createTestClient } from '@eaperezc/mcpgen/testing';
|
|
52
|
+
import { ${className} } from './${className}.js';
|
|
53
|
+
|
|
54
|
+
describe('${className}', () => {
|
|
55
|
+
it('should execute successfully', async () => {
|
|
56
|
+
const client = createTestClient();
|
|
57
|
+
client.registerTool(new ${className}());
|
|
58
|
+
|
|
59
|
+
const result = await client.callTool('${toolName}', { input: 'test' });
|
|
60
|
+
|
|
61
|
+
expect(result.content).toHaveProperty('result');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should require input parameter', async () => {
|
|
65
|
+
const client = createTestClient();
|
|
66
|
+
client.registerTool(new ${className}());
|
|
67
|
+
|
|
68
|
+
await expect(client.callTool('${toolName}', {})).rejects.toThrow();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
49
73
|
function resourceTemplate(className, resourceName) {
|
|
50
|
-
return `import { BaseResource } from '
|
|
74
|
+
return `import { BaseResource } from '@eaperezc/mcpgen';
|
|
51
75
|
|
|
52
76
|
/**
|
|
53
77
|
* ${className} - Description of what this resource provides
|
|
@@ -72,7 +96,7 @@ export class ${className} extends BaseResource {
|
|
|
72
96
|
`;
|
|
73
97
|
}
|
|
74
98
|
function promptTemplate(className, promptName) {
|
|
75
|
-
return `import { BasePrompt } from '
|
|
99
|
+
return `import { BasePrompt } from '@eaperezc/mcpgen';
|
|
76
100
|
import { z } from 'zod';
|
|
77
101
|
|
|
78
102
|
/**
|
|
@@ -121,18 +145,21 @@ async function generateComponent(options) {
|
|
|
121
145
|
const typeDir = type === "tool" ? "tools" : type === "resource" ? "resources" : "prompts";
|
|
122
146
|
const srcDir = path.join(process.cwd(), "src", typeDir);
|
|
123
147
|
const filePath = path.join(srcDir, `${fileName}.ts`);
|
|
148
|
+
const testFilePath = path.join(srcDir, `${fileName}.test.ts`);
|
|
124
149
|
const indexPath = path.join(srcDir, "index.ts");
|
|
125
150
|
if (!await exists(path.join(process.cwd(), "src"))) {
|
|
126
|
-
throw new Error('No src/ directory found. Are you in an
|
|
151
|
+
throw new Error('No src/ directory found. Are you in an mcpgen project? Run "mcpgen init" first.');
|
|
127
152
|
}
|
|
128
153
|
await promises.mkdir(srcDir, { recursive: true });
|
|
129
154
|
if (await exists(filePath)) {
|
|
130
155
|
throw new Error(`${type} '${fileName}' already exists at ${filePath}`);
|
|
131
156
|
}
|
|
132
157
|
let content;
|
|
158
|
+
let testContent = null;
|
|
133
159
|
switch (type) {
|
|
134
160
|
case "tool":
|
|
135
161
|
content = toolTemplate(className, kebabName);
|
|
162
|
+
testContent = toolTestTemplate(className, kebabName);
|
|
136
163
|
break;
|
|
137
164
|
case "resource":
|
|
138
165
|
content = resourceTemplate(className, kebabName);
|
|
@@ -146,6 +173,10 @@ async function generateComponent(options) {
|
|
|
146
173
|
await promises.writeFile(filePath, content);
|
|
147
174
|
console.log(`
|
|
148
175
|
\u2705 Created ${type}: ${filePath.replace(process.cwd(), ".")}`);
|
|
176
|
+
if (testContent) {
|
|
177
|
+
await promises.writeFile(testFilePath, testContent);
|
|
178
|
+
console.log(` Created test: ${testFilePath.replace(process.cwd(), ".")}`);
|
|
179
|
+
}
|
|
149
180
|
await updateIndexFile(indexPath, className, fileName);
|
|
150
181
|
console.log(` Updated: ${indexPath.replace(process.cwd(), ".")}`);
|
|
151
182
|
console.log(`
|
|
@@ -154,8 +185,9 @@ Next steps:
|
|
|
154
185
|
1. Edit src/${typeDir}/${fileName}.ts to implement your ${type}
|
|
155
186
|
2. Register it in src/index.ts:
|
|
156
187
|
|
|
157
|
-
import { ${className} } from '
|
|
188
|
+
import { ${className} } from './${typeDir}/${fileName}.js';
|
|
158
189
|
server.${type}(new ${className}());
|
|
190
|
+
3. Run tests: npm test
|
|
159
191
|
`);
|
|
160
192
|
}
|
|
161
193
|
|
|
@@ -173,7 +205,8 @@ var packageJsonTemplate = (name, description) => `{
|
|
|
173
205
|
"test": "vitest run",
|
|
174
206
|
"test:watch": "vitest",
|
|
175
207
|
"lint": "eslint src",
|
|
176
|
-
"typecheck": "tsc --noEmit"
|
|
208
|
+
"typecheck": "tsc --noEmit",
|
|
209
|
+
"inspector": "npx @modelcontextprotocol/inspector"
|
|
177
210
|
},
|
|
178
211
|
"keywords": ["mcp", "model-context-protocol"],
|
|
179
212
|
"license": "MIT",
|
|
@@ -338,9 +371,9 @@ export class ConfigResource extends BaseResource {
|
|
|
338
371
|
var promptsIndexTemplate = () => `// Export your prompts here
|
|
339
372
|
// export { SummarizePrompt } from './SummarizePrompt.js';
|
|
340
373
|
`;
|
|
341
|
-
var
|
|
374
|
+
var greetToolTestTemplate = () => `import { describe, it, expect } from 'vitest';
|
|
342
375
|
import { createTestClient } from '@eaperezc/mcpgen/testing';
|
|
343
|
-
import { GreetTool } from '
|
|
376
|
+
import { GreetTool } from './GreetTool.js';
|
|
344
377
|
|
|
345
378
|
describe('GreetTool', () => {
|
|
346
379
|
it('should greet the user', async () => {
|
|
@@ -396,19 +429,32 @@ npm start
|
|
|
396
429
|
npm test
|
|
397
430
|
\`\`\`
|
|
398
431
|
|
|
432
|
+
### MCP Inspector
|
|
433
|
+
|
|
434
|
+
To test and debug your server with the MCP Inspector:
|
|
435
|
+
|
|
436
|
+
\`\`\`bash
|
|
437
|
+
# Terminal 1: Start the server
|
|
438
|
+
npm run dev
|
|
439
|
+
|
|
440
|
+
# Terminal 2: Launch the inspector
|
|
441
|
+
npm run inspector
|
|
442
|
+
\`\`\`
|
|
443
|
+
|
|
444
|
+
Then connect to \`http://localhost:3000/mcp\` using **Streamable HTTP** transport.
|
|
445
|
+
|
|
399
446
|
## Project Structure
|
|
400
447
|
|
|
401
448
|
\`\`\`
|
|
402
449
|
${name}/
|
|
403
450
|
\u251C\u2500\u2500 src/
|
|
404
|
-
\u2502 \u251C\u2500\u2500 tools/
|
|
405
|
-
\u2502 \u2502 \
|
|
406
|
-
\u2502 \
|
|
451
|
+
\u2502 \u251C\u2500\u2500 tools/ # MCP tools
|
|
452
|
+
\u2502 \u2502 \u251C\u2500\u2500 GreetTool.ts
|
|
453
|
+
\u2502 \u2502 \u2514\u2500\u2500 GreetTool.test.ts
|
|
454
|
+
\u2502 \u251C\u2500\u2500 resources/ # MCP resources
|
|
407
455
|
\u2502 \u2502 \u2514\u2500\u2500 ConfigResource.ts
|
|
408
|
-
\u2502 \u251C\u2500\u2500 prompts/
|
|
409
|
-
\u2502 \u2514\u2500\u2500 index.ts
|
|
410
|
-
\u251C\u2500\u2500 tests/
|
|
411
|
-
\u2502 \u2514\u2500\u2500 tools.test.ts
|
|
456
|
+
\u2502 \u251C\u2500\u2500 prompts/ # MCP prompts
|
|
457
|
+
\u2502 \u2514\u2500\u2500 index.ts # Server entry point
|
|
412
458
|
\u251C\u2500\u2500 package.json
|
|
413
459
|
\u2514\u2500\u2500 tsconfig.json
|
|
414
460
|
\`\`\`
|
|
@@ -482,7 +528,7 @@ async function initProject(options) {
|
|
|
482
528
|
const {
|
|
483
529
|
name,
|
|
484
530
|
description = `An MCP server built with @eaperezc/mcpgen`,
|
|
485
|
-
transport = "
|
|
531
|
+
transport = "http"
|
|
486
532
|
} = options;
|
|
487
533
|
const projectDir = path.join(process.cwd(), name);
|
|
488
534
|
if (await exists2(projectDir)) {
|
|
@@ -496,8 +542,7 @@ Creating new MCP server: ${name}
|
|
|
496
542
|
path.join(projectDir, "src"),
|
|
497
543
|
path.join(projectDir, "src", "tools"),
|
|
498
544
|
path.join(projectDir, "src", "resources"),
|
|
499
|
-
path.join(projectDir, "src", "prompts")
|
|
500
|
-
path.join(projectDir, "tests")
|
|
545
|
+
path.join(projectDir, "src", "prompts")
|
|
501
546
|
];
|
|
502
547
|
for (const dir of dirs) {
|
|
503
548
|
await promises.mkdir(dir, { recursive: true });
|
|
@@ -512,10 +557,10 @@ Creating new MCP server: ${name}
|
|
|
512
557
|
{ path: "src/index.ts", content: mainIndexTemplate(name, transport) },
|
|
513
558
|
{ path: "src/tools/index.ts", content: toolsIndexTemplate() },
|
|
514
559
|
{ path: "src/tools/GreetTool.ts", content: greetToolTemplate() },
|
|
560
|
+
{ path: "src/tools/GreetTool.test.ts", content: greetToolTestTemplate() },
|
|
515
561
|
{ path: "src/resources/index.ts", content: resourcesIndexTemplate() },
|
|
516
562
|
{ path: "src/resources/ConfigResource.ts", content: configResourceTemplate(name) },
|
|
517
|
-
{ path: "src/prompts/index.ts", content: promptsIndexTemplate() }
|
|
518
|
-
{ path: "tests/tools.test.ts", content: testExampleTemplate() }
|
|
563
|
+
{ path: "src/prompts/index.ts", content: promptsIndexTemplate() }
|
|
519
564
|
];
|
|
520
565
|
for (const file of files) {
|
|
521
566
|
const filePath = path.join(projectDir, file.path);
|
|
@@ -545,7 +590,7 @@ Happy building! \u{1F680}
|
|
|
545
590
|
// src/cli/index.ts
|
|
546
591
|
var program = new commander.Command();
|
|
547
592
|
program.name("mcpgen").description("CLI for building MCP servers").version("0.1.0");
|
|
548
|
-
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 (
|
|
593
|
+
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) => {
|
|
549
594
|
try {
|
|
550
595
|
await initProject({
|
|
551
596
|
name,
|
|
@@ -594,14 +639,15 @@ program.addHelpText(
|
|
|
594
639
|
"after",
|
|
595
640
|
`
|
|
596
641
|
Examples:
|
|
597
|
-
$ mcpgen init my-mcp-server
|
|
598
|
-
$ mcpgen init my-api --transport
|
|
642
|
+
$ mcpgen init my-mcp-server Create a new MCP server (HTTP)
|
|
643
|
+
$ mcpgen init my-api --transport stdio Create with stdio transport
|
|
599
644
|
$ mcpgen make:tool search Create a new tool
|
|
600
645
|
$ mcpgen make:resource database Create a new resource
|
|
601
646
|
$ mcpgen make:prompt summarize Create a new prompt
|
|
602
647
|
`
|
|
603
648
|
);
|
|
604
649
|
if (process.argv.length <= 2) {
|
|
650
|
+
const yellow = "\x1B[33m";
|
|
605
651
|
const cyan = "\x1B[36m";
|
|
606
652
|
const dim = "\x1B[2m";
|
|
607
653
|
const bold = "\x1B[1m";
|
|
@@ -609,7 +655,7 @@ if (process.argv.length <= 2) {
|
|
|
609
655
|
console.log(`
|
|
610
656
|
${dim}+-------------------------------------+${reset}
|
|
611
657
|
${dim}|${reset} ${dim}|${reset}
|
|
612
|
-
${dim}|${reset} ${bold}${
|
|
658
|
+
${dim}|${reset} ${bold}${yellow}MCP-GEN${reset} ${dim}v0.1.0${reset} ${dim}|${reset}
|
|
613
659
|
${dim}|${reset} ${dim}|${reset}
|
|
614
660
|
${dim}|${reset} A TypeScript framework for ${dim}|${reset}
|
|
615
661
|
${dim}|${reset} building MCP servers ${dim}|${reset}
|
package/dist/cli/index.cjs.map
CHANGED
|
@@ -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":["access","readFile","writeFile","join","mkdir","exists","Command"],"mappings":"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","file":"index.cjs","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":["access","readFile","writeFile","join","mkdir","exists","Command"],"mappings":"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","file":"index.cjs","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"]}
|