@webbywisp/create-mcp-server 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +222 -0
- package/dist/cli.js +263 -18
- package/dist/cli.js.map +1 -1
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# @webbywisp/create-mcp-server
|
|
2
|
+
|
|
3
|
+
> Scaffold production-ready MCP (Model Context Protocol) servers in seconds.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @webbywisp/create-mcp-server my-server
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Built for developers who want to expose tools, resources, or prompt templates to AI models — without writing boilerplate.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Interactive wizard (recommended)
|
|
17
|
+
npx @webbywisp/create-mcp-server my-server
|
|
18
|
+
|
|
19
|
+
# Non-interactive, use defaults (tool-server template)
|
|
20
|
+
npx @webbywisp/create-mcp-server my-server --yes
|
|
21
|
+
|
|
22
|
+
# Pick a specific template
|
|
23
|
+
npx @webbywisp/create-mcp-server my-server -t resource-server
|
|
24
|
+
|
|
25
|
+
# Preview what would be created
|
|
26
|
+
npx @webbywisp/create-mcp-server my-server --dry-run
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Commands
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
create-mcp-server [directory] Scaffold a new MCP server (default)
|
|
35
|
+
create-mcp-server init [directory] Scaffold a new MCP server
|
|
36
|
+
create-mcp-server add [type] [name] Add a tool/resource/prompt to an existing server
|
|
37
|
+
create-mcp-server list Show available templates
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Templates
|
|
43
|
+
|
|
44
|
+
### `tool-server` (default)
|
|
45
|
+
Expose callable **tools** to AI models. Great for file I/O, HTTP requests, shell commands, APIs.
|
|
46
|
+
|
|
47
|
+
Generated tools:
|
|
48
|
+
- `read_file` — read file contents with encoding + size limits
|
|
49
|
+
- `write_file` — write files, creating directories as needed
|
|
50
|
+
- `http_fetch` — make HTTP requests (GET, POST, PUT, DELETE)
|
|
51
|
+
- `exec_command` — execute shell commands with safety checks
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx @webbywisp/create-mcp-server my-tools -t tool-server
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `resource-server`
|
|
58
|
+
Expose **data** as addressable URIs. Great for files, databases, config, any content an AI should be able to read.
|
|
59
|
+
|
|
60
|
+
Generated resources:
|
|
61
|
+
- `file://` — list and read files from the filesystem
|
|
62
|
+
- `db://` — query a SQLite database
|
|
63
|
+
- `config://` — expose configuration files
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx @webbywisp/create-mcp-server my-data -t resource-server
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### `prompt-server`
|
|
70
|
+
Expose **structured prompt templates** for common tasks. Great for standardizing code review, debugging, documentation, refactoring workflows.
|
|
71
|
+
|
|
72
|
+
Generated prompts:
|
|
73
|
+
- `code-review` — review code for issues, patterns, suggestions
|
|
74
|
+
- `debug-error` — systematic error analysis
|
|
75
|
+
- `generate-docs` — generate documentation from code
|
|
76
|
+
- `refactor` — refactor code with specific goals
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx @webbywisp/create-mcp-server my-prompts -t prompt-server
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Options
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
-t, --template <name> Template: tool-server | resource-server | prompt-server
|
|
88
|
+
-y, --yes Skip prompts, use defaults
|
|
89
|
+
--dry-run Preview what would be created without writing files
|
|
90
|
+
--force Overwrite existing files
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Generated Structure
|
|
96
|
+
|
|
97
|
+
### tool-server
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
my-server/
|
|
101
|
+
├── src/
|
|
102
|
+
│ ├── index.ts # Server entry point, tool registration
|
|
103
|
+
│ └── tools/
|
|
104
|
+
│ ├── readFile.ts # Read file contents
|
|
105
|
+
│ ├── writeFile.ts # Write files
|
|
106
|
+
│ ├── httpFetch.ts # HTTP requests
|
|
107
|
+
│ └── execCommand.ts # Shell execution (with safety checks)
|
|
108
|
+
├── package.json # MCP SDK + zod dependencies
|
|
109
|
+
├── tsconfig.json # TypeScript config (ES2022, NodeNext)
|
|
110
|
+
├── .gitignore
|
|
111
|
+
└── README.md
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### resource-server
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
my-server/
|
|
118
|
+
├── src/
|
|
119
|
+
│ ├── index.ts # Server entry point, resource registration
|
|
120
|
+
│ └── resources/
|
|
121
|
+
│ ├── fileSystem.ts # file:// URI resources
|
|
122
|
+
│ ├── database.ts # db:// URI resources (SQLite)
|
|
123
|
+
│ └── config.ts # config:// URI resources
|
|
124
|
+
├── package.json
|
|
125
|
+
├── tsconfig.json
|
|
126
|
+
├── .gitignore
|
|
127
|
+
└── README.md
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### prompt-server
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
my-server/
|
|
134
|
+
├── src/
|
|
135
|
+
│ ├── index.ts # Server entry point, prompt registration
|
|
136
|
+
│ └── prompts/
|
|
137
|
+
│ ├── codeReview.ts # Code review prompt
|
|
138
|
+
│ ├── debugError.ts # Error debugging prompt
|
|
139
|
+
│ ├── generateDocs.ts # Documentation generation prompt
|
|
140
|
+
│ └── refactor.ts # Refactoring prompt
|
|
141
|
+
├── package.json
|
|
142
|
+
├── tsconfig.json
|
|
143
|
+
├── .gitignore
|
|
144
|
+
└── README.md
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## After Scaffolding
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
cd my-server
|
|
153
|
+
npm install
|
|
154
|
+
npm run build
|
|
155
|
+
npm start
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Connect to Claude Desktop
|
|
159
|
+
|
|
160
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"mcpServers": {
|
|
165
|
+
"my-server": {
|
|
166
|
+
"command": "node",
|
|
167
|
+
"args": ["/absolute/path/to/my-server/dist/index.js"]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Restart Claude Desktop. Your tools/resources/prompts will be available immediately.
|
|
174
|
+
|
|
175
|
+
### Connect to Other Clients
|
|
176
|
+
|
|
177
|
+
The stdio transport works with any MCP-compliant client. See the [MCP docs](https://modelcontextprotocol.io) for SSE transport and other options.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Adding to an Existing Server
|
|
182
|
+
|
|
183
|
+
The `add` command lets you add individual pieces to a server you've already scaffolded:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Add a new tool file
|
|
187
|
+
create-mcp-server add tool my-custom-tool
|
|
188
|
+
|
|
189
|
+
# Add a new resource handler
|
|
190
|
+
create-mcp-server add resource my-data-source
|
|
191
|
+
|
|
192
|
+
# Add a new prompt template
|
|
193
|
+
create-mcp-server add prompt code-explainer
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Why MCP?
|
|
199
|
+
|
|
200
|
+
The Model Context Protocol (MCP) is an open standard for connecting AI models to external tools and data. Instead of hard-coding API calls inside prompts, MCP lets you:
|
|
201
|
+
|
|
202
|
+
- **Expose tools** — functions AI can call (file ops, HTTP, databases, APIs)
|
|
203
|
+
- **Expose resources** — data AI can read on demand (files, DB records, config)
|
|
204
|
+
- **Expose prompts** — reusable prompt templates with structured inputs
|
|
205
|
+
|
|
206
|
+
AI models discover what's available and call your code directly. Clean separation, standardized interface, works across Claude, OpenAI, and any MCP-compatible client.
|
|
207
|
+
|
|
208
|
+
This CLI scaffolds the full TypeScript setup so you can focus on the logic, not the boilerplate.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Related
|
|
213
|
+
|
|
214
|
+
- [@webbywisp/create-ai-agent](https://www.npmjs.com/package/@webbywisp/create-ai-agent) — scaffold AI agent workspaces (SOUL.md, OPS.md, memory structure)
|
|
215
|
+
- [MCP Specification](https://modelcontextprotocol.io)
|
|
216
|
+
- [AI Agent Workspace Kit](https://webbywisp.gumroad.com/l/ejqpns) — full production agent workspace template ($19)
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import chalk4 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/commands/init.ts
|
|
8
8
|
import path2 from "path";
|
|
@@ -1732,22 +1732,244 @@ function getTemplateFiles(config) {
|
|
|
1732
1732
|
}
|
|
1733
1733
|
}
|
|
1734
1734
|
|
|
1735
|
+
// src/commands/add.ts
|
|
1736
|
+
import path3 from "path";
|
|
1737
|
+
import chalk3 from "chalk";
|
|
1738
|
+
import fs3 from "fs-extra";
|
|
1739
|
+
var TOOL_TEMPLATE = (name) => `import { z } from 'zod';
|
|
1740
|
+
|
|
1741
|
+
export const ${toCamelCase(name)}Tool = {
|
|
1742
|
+
name: '${toSnakeCase(name)}',
|
|
1743
|
+
description: 'Description of what this tool does',
|
|
1744
|
+
inputSchema: {
|
|
1745
|
+
input: z.string().describe('Primary input'),
|
|
1746
|
+
options: z.object({
|
|
1747
|
+
verbose: z.boolean().optional().default(false),
|
|
1748
|
+
}).optional(),
|
|
1749
|
+
},
|
|
1750
|
+
handler: async ({ input, options }: {
|
|
1751
|
+
input: string;
|
|
1752
|
+
options?: { verbose?: boolean };
|
|
1753
|
+
}) => {
|
|
1754
|
+
try {
|
|
1755
|
+
// TODO: Implement tool logic
|
|
1756
|
+
const result = \`Processed: \${input}\`;
|
|
1757
|
+
|
|
1758
|
+
if (options?.verbose) {
|
|
1759
|
+
console.error(\`[${toSnakeCase(name)}] input=\${input}\`);
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
return {
|
|
1763
|
+
content: [{ type: 'text' as const, text: result }],
|
|
1764
|
+
};
|
|
1765
|
+
} catch (err: any) {
|
|
1766
|
+
return {
|
|
1767
|
+
content: [{ type: 'text' as const, text: \`Error: \${err.message}\` }],
|
|
1768
|
+
isError: true,
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
},
|
|
1772
|
+
};
|
|
1773
|
+
`;
|
|
1774
|
+
var RESOURCE_TEMPLATE = (name) => `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1775
|
+
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1776
|
+
|
|
1777
|
+
const SCHEME = '${toKebabCase(name)}://';
|
|
1778
|
+
|
|
1779
|
+
export const ${toCamelCase(name)}Resources = {
|
|
1780
|
+
register(server: McpServer) {
|
|
1781
|
+
// List available resources
|
|
1782
|
+
server.resource(
|
|
1783
|
+
\`\${SCHEME}list\`,
|
|
1784
|
+
new ResourceTemplate(\`\${SCHEME}list\`, { list: undefined }),
|
|
1785
|
+
async (uri) => {
|
|
1786
|
+
// TODO: Return list of available ${name} resources
|
|
1787
|
+
return {
|
|
1788
|
+
contents: [
|
|
1789
|
+
{
|
|
1790
|
+
uri: \`\${SCHEME}example\`,
|
|
1791
|
+
mimeType: 'text/plain',
|
|
1792
|
+
text: 'Example ${name} resource',
|
|
1793
|
+
},
|
|
1794
|
+
],
|
|
1795
|
+
};
|
|
1796
|
+
},
|
|
1797
|
+
);
|
|
1798
|
+
|
|
1799
|
+
// Get a specific resource by ID
|
|
1800
|
+
server.resource(
|
|
1801
|
+
\`\${SCHEME}{id}\`,
|
|
1802
|
+
new ResourceTemplate(\`\${SCHEME}{id}\`, { list: undefined }),
|
|
1803
|
+
async (uri, { id }) => {
|
|
1804
|
+
// TODO: Fetch resource by id
|
|
1805
|
+
return {
|
|
1806
|
+
contents: [
|
|
1807
|
+
{
|
|
1808
|
+
uri: uri.href,
|
|
1809
|
+
mimeType: 'text/plain',
|
|
1810
|
+
text: \`Content for ${name} resource: \${id}\`,
|
|
1811
|
+
},
|
|
1812
|
+
],
|
|
1813
|
+
};
|
|
1814
|
+
},
|
|
1815
|
+
);
|
|
1816
|
+
},
|
|
1817
|
+
};
|
|
1818
|
+
`;
|
|
1819
|
+
var PROMPT_TEMPLATE = (name) => `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1820
|
+
import { z } from 'zod';
|
|
1821
|
+
|
|
1822
|
+
export function register${toPascalCase(name)}Prompt(server: McpServer) {
|
|
1823
|
+
server.prompt(
|
|
1824
|
+
'${toKebabCase(name)}',
|
|
1825
|
+
{
|
|
1826
|
+
// Define prompt arguments
|
|
1827
|
+
input: z.string().describe('Primary input for the ${name} prompt'),
|
|
1828
|
+
context: z.string().optional().describe('Additional context'),
|
|
1829
|
+
focus: z.string().optional().describe('Specific focus area or constraint'),
|
|
1830
|
+
},
|
|
1831
|
+
({ input, context, focus }) => {
|
|
1832
|
+
const contextSection = context ? \`\\n\\nContext:\\n\${context}\` : '';
|
|
1833
|
+
const focusSection = focus ? \`\\n\\nFocus on: \${focus}\` : '';
|
|
1834
|
+
|
|
1835
|
+
return {
|
|
1836
|
+
messages: [
|
|
1837
|
+
{
|
|
1838
|
+
role: 'user',
|
|
1839
|
+
content: {
|
|
1840
|
+
type: 'text',
|
|
1841
|
+
text: \`# ${toPascalCase(name.replace(/-/g, " "))}
|
|
1842
|
+
|
|
1843
|
+
\${input}\${contextSection}\${focusSection}
|
|
1844
|
+
|
|
1845
|
+
Please provide a thorough, structured response.\`,
|
|
1846
|
+
},
|
|
1847
|
+
},
|
|
1848
|
+
],
|
|
1849
|
+
};
|
|
1850
|
+
},
|
|
1851
|
+
);
|
|
1852
|
+
}
|
|
1853
|
+
`;
|
|
1854
|
+
function toCamelCase(str) {
|
|
1855
|
+
return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
|
|
1856
|
+
}
|
|
1857
|
+
function toPascalCase(str) {
|
|
1858
|
+
const camel = toCamelCase(str);
|
|
1859
|
+
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
1860
|
+
}
|
|
1861
|
+
function toSnakeCase(str) {
|
|
1862
|
+
return str.replace(/[-]/g, "_").replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
1863
|
+
}
|
|
1864
|
+
function toKebabCase(str) {
|
|
1865
|
+
return str.replace(/[_]/g, "-").replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
1866
|
+
}
|
|
1867
|
+
async function addCommand(type, name, opts) {
|
|
1868
|
+
console.log();
|
|
1869
|
+
if (!type || !["tool", "resource", "prompt"].includes(type)) {
|
|
1870
|
+
console.log(chalk3.bold("Usage:"));
|
|
1871
|
+
console.log(` ${chalk3.cyan("create-mcp-server add tool <name>")} Add a new tool`);
|
|
1872
|
+
console.log(` ${chalk3.cyan("create-mcp-server add resource <name>")} Add a new resource provider`);
|
|
1873
|
+
console.log(` ${chalk3.cyan("create-mcp-server add prompt <name>")} Add a new prompt template`);
|
|
1874
|
+
console.log();
|
|
1875
|
+
console.log(chalk3.dim("Examples:"));
|
|
1876
|
+
console.log(` ${chalk3.cyan("create-mcp-server add tool github-search")}`);
|
|
1877
|
+
console.log(` ${chalk3.cyan("create-mcp-server add resource postgres-db")}`);
|
|
1878
|
+
console.log(` ${chalk3.cyan("create-mcp-server add prompt summarize")}`);
|
|
1879
|
+
console.log();
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
if (!name) {
|
|
1883
|
+
console.error(chalk3.red(`\u274C Please provide a name: create-mcp-server add ${type} <name>`));
|
|
1884
|
+
process.exit(1);
|
|
1885
|
+
}
|
|
1886
|
+
const cwd = process.cwd();
|
|
1887
|
+
let filePath;
|
|
1888
|
+
let content;
|
|
1889
|
+
let dir;
|
|
1890
|
+
switch (type) {
|
|
1891
|
+
case "tool":
|
|
1892
|
+
dir = path3.join(cwd, "src", "tools");
|
|
1893
|
+
filePath = path3.join(dir, `${toCamelCase(name)}.ts`);
|
|
1894
|
+
content = TOOL_TEMPLATE(name);
|
|
1895
|
+
break;
|
|
1896
|
+
case "resource":
|
|
1897
|
+
dir = path3.join(cwd, "src", "resources");
|
|
1898
|
+
filePath = path3.join(dir, `${toCamelCase(name)}.ts`);
|
|
1899
|
+
content = RESOURCE_TEMPLATE(name);
|
|
1900
|
+
break;
|
|
1901
|
+
case "prompt":
|
|
1902
|
+
dir = path3.join(cwd, "src", "prompts");
|
|
1903
|
+
filePath = path3.join(dir, `${toCamelCase(name)}.ts`);
|
|
1904
|
+
content = PROMPT_TEMPLATE(name);
|
|
1905
|
+
break;
|
|
1906
|
+
default:
|
|
1907
|
+
process.exit(1);
|
|
1908
|
+
}
|
|
1909
|
+
const relativePath = path3.relative(cwd, filePath);
|
|
1910
|
+
if (opts.dryRun) {
|
|
1911
|
+
console.log(chalk3.bold.yellow("\u{1F50D} Dry run \u2014 would create:"));
|
|
1912
|
+
console.log(` ${chalk3.cyan(relativePath)}`);
|
|
1913
|
+
console.log();
|
|
1914
|
+
console.log(chalk3.dim("Run without --dry-run to write the file."));
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
const exists = await fs3.pathExists(filePath);
|
|
1918
|
+
if (exists && !opts.force) {
|
|
1919
|
+
console.error(chalk3.yellow(`\u26A0\uFE0F File already exists: ${relativePath}`));
|
|
1920
|
+
console.error(chalk3.dim(" Use --force to overwrite."));
|
|
1921
|
+
process.exit(1);
|
|
1922
|
+
}
|
|
1923
|
+
await fs3.ensureDir(dir);
|
|
1924
|
+
await fs3.writeFile(filePath, content, "utf8");
|
|
1925
|
+
console.log(chalk3.green(`\u2705 Created ${relativePath}`));
|
|
1926
|
+
console.log();
|
|
1927
|
+
console.log(chalk3.bold("Next:"));
|
|
1928
|
+
console.log(
|
|
1929
|
+
chalk3.dim(
|
|
1930
|
+
` Import and register your new ${type} in ${chalk3.white("src/index.ts")}`
|
|
1931
|
+
)
|
|
1932
|
+
);
|
|
1933
|
+
if (type === "tool") {
|
|
1934
|
+
console.log(chalk3.dim(`
|
|
1935
|
+
import { ${toCamelCase(name)}Tool } from './tools/${toCamelCase(name)}.js';`));
|
|
1936
|
+
console.log(
|
|
1937
|
+
chalk3.dim(
|
|
1938
|
+
` server.tool(${toCamelCase(name)}Tool.name, ${toCamelCase(name)}Tool.description, ${toCamelCase(name)}Tool.inputSchema, ${toCamelCase(name)}Tool.handler);`
|
|
1939
|
+
)
|
|
1940
|
+
);
|
|
1941
|
+
} else if (type === "resource") {
|
|
1942
|
+
console.log(chalk3.dim(`
|
|
1943
|
+
import { ${toCamelCase(name)}Resources } from './resources/${toCamelCase(name)}.js';`));
|
|
1944
|
+
console.log(chalk3.dim(` ${toCamelCase(name)}Resources.register(server);`));
|
|
1945
|
+
} else if (type === "prompt") {
|
|
1946
|
+
console.log(
|
|
1947
|
+
chalk3.dim(
|
|
1948
|
+
`
|
|
1949
|
+
import { register${toPascalCase(name)}Prompt } from './prompts/${toCamelCase(name)}.js';`
|
|
1950
|
+
)
|
|
1951
|
+
);
|
|
1952
|
+
console.log(chalk3.dim(` register${toPascalCase(name)}Prompt(server);`));
|
|
1953
|
+
}
|
|
1954
|
+
console.log();
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1735
1957
|
// src/cli.ts
|
|
1736
|
-
var VERSION = "0.
|
|
1958
|
+
var VERSION = "0.2.0";
|
|
1737
1959
|
var program = new Command();
|
|
1738
1960
|
program.name("create-mcp-server").description("Scaffold production-ready MCP (Model Context Protocol) servers").version(VERSION, "-v, --version", "Show version").addHelpText(
|
|
1739
1961
|
"after",
|
|
1740
1962
|
`
|
|
1741
|
-
${
|
|
1742
|
-
${
|
|
1743
|
-
${
|
|
1744
|
-
${
|
|
1745
|
-
${
|
|
1746
|
-
|
|
1747
|
-
${
|
|
1748
|
-
${
|
|
1749
|
-
${
|
|
1750
|
-
${
|
|
1963
|
+
${chalk4.bold("Examples:")}
|
|
1964
|
+
${chalk4.cyan("npx @webbywisp/create-mcp-server my-server")} Scaffold with prompts
|
|
1965
|
+
${chalk4.cyan("npx @webbywisp/create-mcp-server my-server --yes")} Use all defaults (tool-server)
|
|
1966
|
+
${chalk4.cyan("npx @webbywisp/create-mcp-server my-server -t resource-server")} Use resource-server template
|
|
1967
|
+
${chalk4.cyan("npx @webbywisp/create-mcp-server my-server --dry-run")} Preview without writing files
|
|
1968
|
+
|
|
1969
|
+
${chalk4.bold("Templates:")}
|
|
1970
|
+
${chalk4.cyan("tool-server")} Expose tools (functions AI can call) \u2014 file I/O, HTTP, exec
|
|
1971
|
+
${chalk4.cyan("resource-server")} Expose data as addressable URIs \u2014 files, DB, config
|
|
1972
|
+
${chalk4.cyan("prompt-server")} Provide structured prompt templates \u2014 review, debug, refactor
|
|
1751
1973
|
`
|
|
1752
1974
|
);
|
|
1753
1975
|
program.command("init [directory]", { isDefault: true }).description("Scaffold a new MCP server (default command)").option("-t, --template <name>", "Template: tool-server | resource-server | prompt-server", "tool-server").option("-y, --yes", "Skip prompts, use all defaults").option("--dry-run", "Preview what would be created without writing files").option("--force", "Overwrite existing files").action(async (dir, opts) => {
|
|
@@ -1762,9 +1984,32 @@ program.command("init [directory]", { isDefault: true }).description("Scaffold a
|
|
|
1762
1984
|
handleError(err);
|
|
1763
1985
|
}
|
|
1764
1986
|
});
|
|
1987
|
+
program.command("add [type] [name]").description("Add a tool, resource, or prompt to an existing server").addHelpText(
|
|
1988
|
+
"after",
|
|
1989
|
+
`
|
|
1990
|
+
${chalk4.bold("Types:")}
|
|
1991
|
+
${chalk4.cyan("tool")} Add a new tool file (callable function)
|
|
1992
|
+
${chalk4.cyan("resource")} Add a new resource provider (addressable URI)
|
|
1993
|
+
${chalk4.cyan("prompt")} Add a new prompt template
|
|
1994
|
+
|
|
1995
|
+
${chalk4.bold("Examples:")}
|
|
1996
|
+
${chalk4.cyan("create-mcp-server add tool github-search")}
|
|
1997
|
+
${chalk4.cyan("create-mcp-server add resource postgres-db")}
|
|
1998
|
+
${chalk4.cyan("create-mcp-server add prompt summarize --dry-run")}
|
|
1999
|
+
`
|
|
2000
|
+
).option("--force", "Overwrite existing files").option("--dry-run", "Preview without writing").action(async (type, name, opts) => {
|
|
2001
|
+
try {
|
|
2002
|
+
await addCommand(type, name, {
|
|
2003
|
+
force: opts.force,
|
|
2004
|
+
dryRun: opts.dryRun
|
|
2005
|
+
});
|
|
2006
|
+
} catch (err) {
|
|
2007
|
+
handleError(err);
|
|
2008
|
+
}
|
|
2009
|
+
});
|
|
1765
2010
|
program.command("list").description("Show available templates").action(() => {
|
|
1766
2011
|
console.log();
|
|
1767
|
-
console.log(
|
|
2012
|
+
console.log(chalk4.bold("Available Templates:"));
|
|
1768
2013
|
console.log();
|
|
1769
2014
|
const templates = [
|
|
1770
2015
|
{
|
|
@@ -1784,20 +2029,20 @@ program.command("list").description("Show available templates").action(() => {
|
|
|
1784
2029
|
}
|
|
1785
2030
|
];
|
|
1786
2031
|
templates.forEach(({ name, desc, includes }) => {
|
|
1787
|
-
console.log(` ${
|
|
1788
|
-
console.log(` ${" ".repeat(18)} ${
|
|
2032
|
+
console.log(` ${chalk4.cyan.bold(name.padEnd(18))} ${desc}`);
|
|
2033
|
+
console.log(` ${" ".repeat(18)} ${chalk4.dim("Includes: " + includes)}`);
|
|
1789
2034
|
console.log();
|
|
1790
2035
|
});
|
|
1791
2036
|
});
|
|
1792
2037
|
function handleError(err) {
|
|
1793
2038
|
if (err instanceof Error) {
|
|
1794
|
-
console.error(
|
|
2039
|
+
console.error(chalk4.red(`
|
|
1795
2040
|
\u274C Error: ${err.message}`));
|
|
1796
2041
|
if (process.env.DEBUG) {
|
|
1797
|
-
console.error(
|
|
2042
|
+
console.error(chalk4.dim(err.stack ?? ""));
|
|
1798
2043
|
}
|
|
1799
2044
|
} else {
|
|
1800
|
-
console.error(
|
|
2045
|
+
console.error(chalk4.red("\n\u274C An unexpected error occurred"));
|
|
1801
2046
|
console.error(err);
|
|
1802
2047
|
}
|
|
1803
2048
|
process.exit(1);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/utils/prompts.ts","../src/utils/files.ts","../src/templates/tool-server.ts","../src/templates/resource-server.ts","../src/templates/prompt-server.ts"],"sourcesContent":["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\n\nconst VERSION = '0.1.0';\n\nconst program = new Command();\n\nprogram\n .name('create-mcp-server')\n .description('Scaffold production-ready MCP (Model Context Protocol) servers')\n .version(VERSION, '-v, --version', 'Show version')\n .addHelpText(\n 'after',\n `\n${chalk.bold('Examples:')}\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server')} Scaffold with prompts\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server --yes')} Use all defaults (tool-server)\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server -t resource-server')} Use resource-server template\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server --dry-run')} Preview without writing files\n\n${chalk.bold('Templates:')}\n ${chalk.cyan('tool-server')} Expose tools (functions AI can call) — file I/O, HTTP, exec\n ${chalk.cyan('resource-server')} Expose data as addressable URIs — files, DB, config\n ${chalk.cyan('prompt-server')} Provide structured prompt templates — review, debug, refactor\n`,\n );\n\n// ─── init command (default) ───────────────────────────────────────────────────\n\nprogram\n .command('init [directory]', { isDefault: true })\n .description('Scaffold a new MCP server (default command)')\n .option('-t, --template <name>', 'Template: tool-server | resource-server | prompt-server', 'tool-server')\n .option('-y, --yes', 'Skip prompts, use all defaults')\n .option('--dry-run', 'Preview what would be created without writing files')\n .option('--force', 'Overwrite existing files')\n .action(async (dir: string | undefined, opts) => {\n try {\n await initCommand(dir, {\n template: opts.template,\n yes: opts.yes,\n dryRun: opts.dryRun,\n force: opts.force,\n });\n } catch (err) {\n handleError(err);\n }\n });\n\n// ─── list command ─────────────────────────────────────────────────────────────\n\nprogram\n .command('list')\n .description('Show available templates')\n .action(() => {\n console.log();\n console.log(chalk.bold('Available Templates:'));\n console.log();\n\n const templates = [\n {\n name: 'tool-server',\n desc: 'Expose callable tools to AI models',\n includes: 'read_file, write_file, http_fetch, exec_command',\n },\n {\n name: 'resource-server',\n desc: 'Expose data as addressable resources',\n includes: 'file://, db://, config:// URI schemes',\n },\n {\n name: 'prompt-server',\n desc: 'Provide structured prompt templates',\n includes: 'code-review, debug-error, generate-docs, refactor',\n },\n ];\n\n templates.forEach(({ name, desc, includes }) => {\n console.log(` ${chalk.cyan.bold(name.padEnd(18))} ${desc}`);\n console.log(` ${' '.repeat(18)} ${chalk.dim('Includes: ' + includes)}`);\n console.log();\n });\n });\n\n// ─── Error handler ─────────────────────────────────────────────────────────\n\nfunction handleError(err: unknown): void {\n if (err instanceof Error) {\n console.error(chalk.red(`\\n❌ Error: ${err.message}`));\n if (process.env.DEBUG) {\n console.error(chalk.dim(err.stack ?? ''));\n }\n } else {\n console.error(chalk.red('\\n❌ An unexpected error occurred'));\n console.error(err);\n }\n process.exit(1);\n}\n\n// ─── Parse ─────────────────────────────────────────────────────────────────\n\nprogram.parseAsync(process.argv).catch(handleError);\n","import path from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport fs from 'fs-extra';\n\nimport type { ServerConfig, Template } from '../types.js';\nimport { runWizard, buildDefaultConfig } from '../utils/prompts.js';\nimport { writeFiles, printDryRunTree, printWriteResults } from '../utils/files.js';\nimport { generateToolServer } from '../templates/tool-server.js';\nimport { generateResourceServer } from '../templates/resource-server.js';\nimport { generatePromptServer } from '../templates/prompt-server.js';\nimport type { GeneratedFile } from '../types.js';\n\nexport interface InitOptions {\n template?: string;\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n}\n\nexport async function initCommand(dirArg: string | undefined, opts: InitOptions): Promise<void> {\n const targetName = dirArg ?? '.';\n const targetDir = path.resolve(process.cwd(), targetName);\n const dirName = path.basename(targetDir);\n\n console.log();\n console.log(chalk.bold.cyan('⚡ create-mcp-server') + chalk.dim(' — scaffold your MCP server'));\n console.log();\n\n // Check existing directory\n const targetExists = await fs.pathExists(targetDir);\n if (targetExists && !opts.dryRun) {\n const entries = await fs.readdir(targetDir).catch(() => []);\n const hasContent = entries.some((e: string) => !e.startsWith('.'));\n if (hasContent && !opts.force) {\n console.log(chalk.yellow(`⚠️ Directory ${chalk.bold(targetDir)} already has files.`));\n console.log(chalk.dim(' Existing files will be skipped. Use --force to overwrite.'));\n console.log();\n }\n }\n\n // Gather config\n let config: ServerConfig;\n const isInteractive = !opts.yes && process.stdin.isTTY;\n\n if (isInteractive) {\n const answers = await runWizard({\n serverName: dirName !== '.' ? dirName : undefined,\n template: opts.template as Template | undefined,\n });\n\n config = buildDefaultConfig(targetDir, dirName, {\n serverName: answers.serverName,\n serverDescription: answers.serverDescription,\n template: answers.template,\n packageName: answers.packageName,\n author: answers.author,\n gitInit: answers.gitInit,\n dryRun: opts.dryRun ?? false,\n });\n } else {\n config = buildDefaultConfig(targetDir, dirName, {\n serverName: dirName !== '.' ? dirName : 'my-mcp-server',\n packageName: dirName !== '.' ? dirName : 'my-mcp-server',\n template: (opts.template as Template) ?? 'tool-server',\n dryRun: opts.dryRun ?? false,\n yes: true,\n });\n console.log(chalk.dim(`Running with defaults. Template: ${config.template}`));\n console.log();\n }\n\n // Generate files\n const files = getTemplateFiles(config);\n\n // Dry run\n if (config.dryRun) {\n console.log(chalk.bold.yellow('🔍 Dry run — no files will be written\\n'));\n printDryRunTree(config.targetDir, files);\n console.log(chalk.dim(` ${files.length} files would be created`));\n console.log();\n console.log(chalk.dim('Run without --dry-run to scaffold the server.'));\n return;\n }\n\n // Write files\n const spinner = ora('Scaffolding MCP server...').start();\n let results;\n\n try {\n results = await writeFiles(config.targetDir, files, opts.force ?? false);\n spinner.succeed('Server scaffolded');\n } catch (err) {\n spinner.fail('Failed to write files');\n throw err;\n }\n\n // Git init\n if (config.gitInit) {\n const gitSpinner = ora('Initializing git...').start();\n try {\n const { simpleGit } = await import('simple-git');\n const git = simpleGit(config.targetDir);\n const isRepo = await git.checkIsRepo().catch(() => false);\n if (!isRepo) {\n await git.init();\n gitSpinner.succeed('Git repository initialized');\n } else {\n gitSpinner.info('Git already initialized, skipped');\n }\n } catch {\n gitSpinner.warn('Git init failed (git may not be installed)');\n }\n }\n\n // Summary\n const created = results.filter((r) => r.status === 'created');\n const skipped = results.filter((r) => r.status === 'skipped');\n\n console.log();\n console.log(chalk.bold.green('✅ MCP server scaffolded at ') + chalk.bold(config.targetDir));\n console.log();\n printWriteResults(results);\n\n console.log();\n console.log(chalk.dim(` ${created.length} file(s) created${skipped.length > 0 ? `, ${skipped.length} skipped` : ''}`));\n\n // Next steps\n console.log();\n console.log(chalk.bold('Next steps:'));\n\n const rel = path.relative(process.cwd(), config.targetDir);\n if (rel && rel !== '.') {\n console.log(` ${chalk.cyan(`cd ${rel}`)}`);\n }\n console.log(` ${chalk.cyan('npm install')}`);\n console.log(` ${chalk.cyan('npm run build')}`);\n console.log(` ${chalk.cyan('npm start')}`);\n console.log();\n console.log(chalk.dim(' Then add to Claude Desktop config:'));\n console.log(chalk.dim(` \"command\": \"node\", \"args\": [\"${config.targetDir}/dist/index.js\"]`));\n console.log();\n console.log(chalk.dim(' See README.md for full setup instructions.'));\n console.log();\n}\n\nfunction getTemplateFiles(config: ServerConfig): GeneratedFile[] {\n switch (config.template) {\n case 'tool-server':\n return generateToolServer(config);\n case 'resource-server':\n return generateResourceServer(config);\n case 'prompt-server':\n return generatePromptServer(config);\n default:\n return generateToolServer(config);\n }\n}\n","import inquirer from 'inquirer';\nimport type { ServerConfig, Template } from '../types.js';\n\nexport interface WizardAnswers {\n serverName: string;\n serverDescription: string;\n template: Template;\n packageName: string;\n author: string;\n gitInit: boolean;\n}\n\nexport async function runWizard(defaults?: Partial<WizardAnswers>): Promise<WizardAnswers> {\n return inquirer.prompt<WizardAnswers>([\n {\n type: 'input',\n name: 'serverName',\n message: 'Server name (used in MCP config):',\n default: defaults?.serverName ?? 'my-mcp-server',\n validate: (input: string) => {\n if (!input.trim()) return 'Server name cannot be empty';\n if (!/^[a-z0-9-]+$/.test(input)) return 'Use lowercase letters, numbers, and hyphens only';\n return true;\n },\n },\n {\n type: 'input',\n name: 'serverDescription',\n message: 'Short description:',\n default: defaults?.serverDescription ?? 'An MCP server',\n },\n {\n type: 'list',\n name: 'template',\n message: 'Choose a template:',\n default: defaults?.template ?? 'tool-server',\n choices: [\n {\n name: 'tool-server — expose tools (functions AI can call)',\n value: 'tool-server',\n short: 'tool-server',\n },\n {\n name: 'resource-server — expose data/files as addressable resources',\n value: 'resource-server',\n short: 'resource-server',\n },\n {\n name: 'prompt-server — provide structured prompt templates',\n value: 'prompt-server',\n short: 'prompt-server',\n },\n ],\n },\n {\n type: 'input',\n name: 'packageName',\n message: 'npm package name:',\n default: (answers: WizardAnswers) => defaults?.packageName ?? answers.serverName,\n validate: (input: string) => {\n if (!input.trim()) return 'Package name cannot be empty';\n return true;\n },\n },\n {\n type: 'input',\n name: 'author',\n message: 'Author name:',\n default: defaults?.author ?? '',\n },\n {\n type: 'confirm',\n name: 'gitInit',\n message: 'Initialize a git repository?',\n default: defaults?.gitInit ?? true,\n },\n ]);\n}\n\nexport function buildDefaultConfig(\n targetDir: string,\n dirName: string,\n overrides: Partial<ServerConfig> = {},\n): ServerConfig {\n return {\n targetDir,\n dirName,\n serverName: dirName,\n serverDescription: `An MCP server`,\n template: 'tool-server',\n packageName: dirName,\n author: '',\n gitInit: true,\n dryRun: false,\n yes: false,\n ...overrides,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport type { GeneratedFile, WriteResult } from '../types.js';\n\nexport async function writeFiles(\n targetDir: string,\n files: GeneratedFile[],\n force: boolean,\n): Promise<WriteResult[]> {\n const results: WriteResult[] = [];\n\n for (const file of files) {\n const filePath = path.join(targetDir, file.path);\n\n if (file.isDirectory) {\n await fs.ensureDir(filePath);\n results.push({ path: file.path, status: 'created' });\n continue;\n }\n\n await fs.ensureDir(path.dirname(filePath));\n\n const exists = await fs.pathExists(filePath);\n\n if (exists && !force) {\n results.push({ path: file.path, status: 'skipped' });\n continue;\n }\n\n await fs.writeFile(filePath, file.content, 'utf8');\n results.push({ path: file.path, status: exists ? 'overwritten' : 'created' });\n }\n\n return results;\n}\n\nexport function printDryRunTree(targetDir: string, files: GeneratedFile[]): void {\n console.log(chalk.bold(`📁 ${targetDir}/`));\n for (const file of files) {\n const icon = file.isDirectory ? '📁' : '📄';\n console.log(chalk.dim(` ${icon} ${file.path}`));\n }\n console.log();\n}\n\nexport function printWriteResults(results: WriteResult[]): void {\n for (const result of results) {\n if (result.status === 'created') {\n console.log(` ${chalk.green('+')} ${result.path}`);\n } else if (result.status === 'overwritten') {\n console.log(` ${chalk.yellow('~')} ${result.path} ${chalk.dim('(overwritten)')}`);\n } else {\n console.log(` ${chalk.dim('-')} ${result.path} ${chalk.dim('(skipped)')}`);\n }\n }\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generateToolServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { readFileTool } from './tools/readFile.js';\nimport { writeFileTool } from './tools/writeFile.js';\nimport { httpFetchTool } from './tools/httpFetch.js';\nimport { execCommandTool } from './tools/execCommand.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register all tools\nserver.tool(\n readFileTool.name,\n readFileTool.description,\n readFileTool.inputSchema,\n readFileTool.handler,\n);\n\nserver.tool(\n writeFileTool.name,\n writeFileTool.description,\n writeFileTool.inputSchema,\n writeFileTool.handler,\n);\n\nserver.tool(\n httpFetchTool.name,\n httpFetchTool.description,\n httpFetchTool.inputSchema,\n httpFetchTool.handler,\n);\n\nserver.tool(\n execCommandTool.name,\n execCommandTool.description,\n execCommandTool.inputSchema,\n execCommandTool.handler,\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/tools/readFile.ts',\n content: `import { z } from 'zod';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const readFileTool = {\n name: 'read_file',\n description: 'Read the contents of a file. Returns the file content as a string.',\n inputSchema: {\n path: z.string().describe('Absolute or relative path to the file'),\n encoding: z.enum(['utf8', 'base64']).optional().default('utf8').describe('File encoding'),\n maxBytes: z.number().optional().default(1048576).describe('Max bytes to read (default 1MB)'),\n },\n handler: async ({ path: filePath, encoding, maxBytes }: {\n path: string;\n encoding?: 'utf8' | 'base64';\n maxBytes?: number;\n }) => {\n const resolvedPath = path.resolve(filePath);\n \n try {\n const stat = await fs.stat(resolvedPath);\n \n if (!stat.isFile()) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: \\${filePath} is not a file\\` }],\n isError: true,\n };\n }\n \n if (stat.size > (maxBytes ?? 1048576)) {\n return {\n content: [{ \n type: 'text' as const, \n text: \\`Error: File too large (\\${stat.size} bytes). Max is \\${maxBytes} bytes.\\` \n }],\n isError: true,\n };\n }\n \n const content = await fs.readFile(resolvedPath, encoding ?? 'utf8');\n \n return {\n content: [{ type: 'text' as const, text: String(content) }],\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`Error reading file: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/writeFile.ts',\n content: `import { z } from 'zod';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const writeFileTool = {\n name: 'write_file',\n description: 'Write content to a file. Creates parent directories if needed.',\n inputSchema: {\n path: z.string().describe('Absolute or relative path to write to'),\n content: z.string().describe('Content to write'),\n encoding: z.enum(['utf8', 'base64']).optional().default('utf8').describe('File encoding'),\n createDirs: z.boolean().optional().default(true).describe('Create parent directories if missing'),\n overwrite: z.boolean().optional().default(true).describe('Overwrite if file exists'),\n },\n handler: async ({ path: filePath, content, encoding, createDirs, overwrite }: {\n path: string;\n content: string;\n encoding?: 'utf8' | 'base64';\n createDirs?: boolean;\n overwrite?: boolean;\n }) => {\n const resolvedPath = path.resolve(filePath);\n \n try {\n // Check if file exists\n if (!overwrite) {\n const exists = await fs.access(resolvedPath).then(() => true).catch(() => false);\n if (exists) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: File already exists at \\${filePath}. Set overwrite=true to overwrite.\\` }],\n isError: true,\n };\n }\n }\n \n if (createDirs) {\n await fs.mkdir(path.dirname(resolvedPath), { recursive: true });\n }\n \n await fs.writeFile(resolvedPath, content, encoding ?? 'utf8');\n \n return {\n content: [{ type: 'text' as const, text: \\`Successfully wrote \\${content.length} bytes to \\${filePath}\\` }],\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`Error writing file: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/httpFetch.ts',\n content: `import { z } from 'zod';\n\nexport const httpFetchTool = {\n name: 'http_fetch',\n description: 'Make an HTTP request and return the response. Supports GET, POST, PUT, DELETE.',\n inputSchema: {\n url: z.string().url().describe('URL to fetch'),\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).optional().default('GET').describe('HTTP method'),\n headers: z.record(z.string()).optional().describe('Request headers as key-value pairs'),\n body: z.string().optional().describe('Request body (for POST/PUT/PATCH)'),\n timeoutMs: z.number().optional().default(30000).describe('Timeout in milliseconds'),\n maxBytes: z.number().optional().default(524288).describe('Max response bytes (default 512KB)'),\n },\n handler: async ({ url, method, headers, body, timeoutMs, maxBytes }: {\n url: string;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeoutMs?: number;\n maxBytes?: number;\n }) => {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs ?? 30000);\n \n const response = await fetch(url, {\n method: method ?? 'GET',\n headers: headers,\n body: body,\n signal: controller.signal,\n });\n \n clearTimeout(timeout);\n \n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n \n const contentType = response.headers.get('content-type') ?? '';\n let responseText: string;\n \n if (contentType.includes('application/json') || contentType.includes('text/')) {\n const arrayBuffer = await response.arrayBuffer();\n const bytes = arrayBuffer.byteLength;\n if (bytes > (maxBytes ?? 524288)) {\n responseText = \\`[Response truncated: \\${bytes} bytes exceeds maxBytes limit]\\`;\n } else {\n responseText = new TextDecoder().decode(arrayBuffer);\n }\n } else {\n responseText = \\`[Binary content: \\${contentType}]\\`;\n }\n \n const summary = [\n \\`Status: \\${response.status} \\${response.statusText}\\`,\n \\`Content-Type: \\${contentType}\\`,\n \\`\\\\n\\${responseText}\\`,\n ].join('\\\\n');\n \n return {\n content: [{ type: 'text' as const, text: summary }],\n isError: !response.ok,\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`HTTP request failed: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/execCommand.ts',\n content: `import { z } from 'zod';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n// Safety: block dangerous commands by default\nconst BLOCKED_PATTERNS = [\n /rm\\\\s+-rf\\\\s+\\\\//,\n /mkfs/,\n /dd\\\\s+if=/,\n /:(\\\\s*)\\\\{\\\\s*:\\\\|:&\\\\s*\\\\}/, // fork bomb\n />\\\\/dev\\\\/(sd|hd|nvme)/,\n];\n\nexport const execCommandTool = {\n name: 'exec_command',\n description: 'Execute a shell command and return stdout/stderr. Use with caution.',\n inputSchema: {\n command: z.string().describe('Shell command to execute'),\n cwd: z.string().optional().describe('Working directory (defaults to process cwd)'),\n timeoutMs: z.number().optional().default(30000).describe('Timeout in milliseconds'),\n env: z.record(z.string()).optional().describe('Additional environment variables'),\n },\n handler: async ({ command, cwd, timeoutMs, env }: {\n command: string;\n cwd?: string;\n timeoutMs?: number;\n env?: Record<string, string>;\n }) => {\n // Safety check\n for (const pattern of BLOCKED_PATTERNS) {\n if (pattern.test(command)) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: Command blocked for safety: \\${command}\\` }],\n isError: true,\n };\n }\n }\n \n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: cwd ?? process.cwd(),\n timeout: timeoutMs ?? 30000,\n env: { ...process.env, ...env },\n maxBuffer: 1024 * 1024, // 1MB\n });\n \n const output = [\n stdout && \\`stdout:\\\\n\\${stdout.trim()}\\`,\n stderr && \\`stderr:\\\\n\\${stderr.trim()}\\`,\n ].filter(Boolean).join('\\\\n\\\\n') || '(no output)';\n \n return {\n content: [{ type: 'text' as const, text: output }],\n };\n } catch (err: any) {\n const output = [\n \\`Exit code: \\${err.code ?? 'unknown'}\\`,\n err.stdout && \\`stdout:\\\\n\\${err.stdout.trim()}\\`,\n err.stderr && \\`stderr:\\\\n\\${err.stderr.trim()}\\`,\n \\`Error: \\${err.message}\\`,\n ].filter(Boolean).join('\\\\n');\n \n return {\n content: [{ type: 'text' as const, text: output }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n zod: '^3.22.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) tool server that exposes file system, HTTP, and shell execution capabilities to AI models.\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| \\`read_file\\` | Read file contents with encoding and size limits |\n| \\`write_file\\` | Write files, creating directories as needed |\n| \\`http_fetch\\` | Make HTTP requests (GET, POST, PUT, DELETE) |\n| \\`exec_command\\` | Execute shell commands with safety checks |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\nAdd to your Claude Desktop config (\\`~/Library/Application Support/Claude/claude_desktop_config.json\\`):\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Adding Tools\n\nCreate a new file in \\`src/tools/\\` following the existing pattern:\n\n\\`\\`\\`typescript\nimport { z } from 'zod';\n\nexport const myTool = {\n name: 'my_tool',\n description: 'Description of what this tool does',\n inputSchema: {\n param1: z.string().describe('First parameter'),\n param2: z.number().optional().describe('Optional number'),\n },\n handler: async ({ param1, param2 }) => {\n // Your implementation\n return {\n content: [{ type: 'text' as const, text: 'result' }],\n };\n },\n};\n\\`\\`\\`\n\nThen register it in \\`src/index.ts\\`.\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generateResourceServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { fileSystemResources } from './resources/fileSystem.js';\nimport { databaseResources } from './resources/database.js';\nimport { configResources } from './resources/config.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register resource providers\nfileSystemResources.register(server);\ndatabaseResources.register(server);\nconfigResources.register(server);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP resource server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/resources/fileSystem.ts',\n content: `import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport fs from 'fs/promises';\nimport path from 'path';\n\n/**\n * File system resources — expose files and directories as MCP resources.\n * URI pattern: file:///absolute/path/to/file\n */\nexport const fileSystemResources = {\n register(server: McpServer) {\n // Static resource: list files in a directory\n server.resource(\n 'workspace-files',\n 'file:///workspace',\n async (uri) => {\n const dir = process.cwd();\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const listing = entries\n .map((e) => \\`\\${e.isDirectory() ? '[dir]' : '[file]'} \\${e.name}\\`)\n .join('\\\\n');\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: \\`Files in \\${dir}:\\\\n\\\\n\\${listing}\\`,\n }],\n };\n } catch (err: any) {\n throw new Error(\\`Failed to list directory: \\${err.message}\\`);\n }\n },\n );\n\n // Dynamic resource template: read any file by URI\n server.resource(\n 'file',\n new ResourceTemplate('file://{path}', { list: undefined }),\n async (uri, params) => {\n const filePath = decodeURIComponent(params.path as string);\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(process.cwd(), filePath);\n \n try {\n const stat = await fs.stat(resolvedPath);\n \n if (stat.isDirectory()) {\n const entries = await fs.readdir(resolvedPath, { withFileTypes: true });\n const listing = entries\n .map((e) => \\`\\${e.isDirectory() ? '[dir] ' : '[file]'} \\${e.name}\\`)\n .join('\\\\n');\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: listing,\n }],\n };\n }\n \n const ext = path.extname(resolvedPath).toLowerCase();\n const textExtensions = new Set([\n '.ts', '.tsx', '.js', '.jsx', '.json', '.md', '.txt', \n '.yaml', '.yml', '.toml', '.env', '.sh', '.bash', '.zsh',\n '.py', '.rb', '.go', '.rs', '.java', '.c', '.cpp', '.h',\n '.html', '.css', '.scss', '.less', '.xml', '.svg',\n ]);\n \n if (textExtensions.has(ext) || stat.size < 100000) {\n const content = await fs.readFile(resolvedPath, 'utf8');\n const mimeType = getMimeType(ext);\n \n return {\n contents: [{\n uri: uri.href,\n mimeType,\n text: content,\n }],\n };\n } else {\n const data = await fs.readFile(resolvedPath);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/octet-stream',\n blob: data.toString('base64'),\n }],\n };\n }\n } catch (err: any) {\n throw new Error(\\`Failed to read file \\${resolvedPath}: \\${err.message}\\`);\n }\n },\n );\n },\n};\n\nfunction getMimeType(ext: string): string {\n const map: Record<string, string> = {\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.js': 'text/javascript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.md': 'text/markdown',\n '.txt': 'text/plain',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.html': 'text/html',\n '.css': 'text/css',\n '.svg': 'image/svg+xml',\n '.xml': 'application/xml',\n '.py': 'text/x-python',\n '.sh': 'text/x-sh',\n };\n return map[ext] ?? 'text/plain';\n}\n`,\n },\n {\n path: 'src/resources/database.ts',\n content: `import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\n\n// Example: In-memory key-value store as a resource.\n// Replace with your actual data source (SQLite, Postgres, Redis, etc.)\nconst store = new Map<string, unknown>([\n ['example:config', { version: '1.0', feature_flags: { new_ui: true } }],\n ['example:stats', { requests: 0, errors: 0, uptime: Date.now() }],\n]);\n\n/**\n * Database/store resources — expose structured data as MCP resources.\n * URI pattern: db://namespace/key\n * \n * Replace the in-memory store with your actual database client.\n */\nexport const databaseResources = {\n register(server: McpServer) {\n // List all available keys\n server.resource(\n 'db-index',\n 'db://index',\n async (uri) => {\n const keys = Array.from(store.keys());\n const listing = keys.map(k => \\` \\${k}\\`).join('\\\\n');\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: \\`Available keys (\\${keys.length}):\\\\n\\${listing}\\`,\n }],\n };\n },\n );\n\n // Dynamic resource: fetch any key\n server.resource(\n 'db-record',\n new ResourceTemplate('db://{namespace}/{key}', { list: undefined }),\n async (uri, params) => {\n const recordKey = \\`\\${params.namespace}:\\${params.key}\\`;\n const value = store.get(recordKey);\n \n if (value === undefined) {\n throw new Error(\\`Key not found: \\${recordKey}\\`);\n }\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(value, null, 2),\n }],\n };\n },\n );\n },\n};\n`,\n },\n {\n path: 'src/resources/config.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport fs from 'fs/promises';\nimport path from 'path';\n\n/**\n * Config resources — expose runtime config, env vars, and app settings.\n * \n * These are useful for giving the AI context about the environment\n * without exposing sensitive credentials.\n */\nexport const configResources = {\n register(server: McpServer) {\n // Expose safe environment info\n server.resource(\n 'environment',\n 'config://environment',\n async (uri) => {\n const safeEnv: Record<string, string> = {};\n \n // Only expose non-sensitive env vars\n const allowedPrefixes = ['NODE_', 'npm_', 'PATH', 'HOME', 'USER', 'SHELL', 'LANG'];\n const blockedKeys = ['TOKEN', 'SECRET', 'PASSWORD', 'KEY', 'PRIVATE', 'AUTH', 'CREDENTIAL'];\n \n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue;\n \n const isBlocked = blockedKeys.some(b => key.toUpperCase().includes(b));\n if (isBlocked) continue;\n \n safeEnv[key] = value;\n }\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify({\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n cwd: process.cwd(),\n env: safeEnv,\n }, null, 2),\n }],\n };\n },\n );\n\n // Expose package.json info\n server.resource(\n 'package-info',\n 'config://package',\n async (uri) => {\n try {\n const pkgPath = path.resolve(process.cwd(), 'package.json');\n const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));\n \n // Strip sensitive fields\n const { _authToken, publishConfig, ...safePkg } = pkg;\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(safePkg, null, 2),\n }],\n };\n } catch {\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: 'No package.json found in current directory',\n }],\n };\n }\n },\n );\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) resource server that exposes file system, database, and configuration data as addressable resources.\n\n## Resources\n\n| URI Pattern | Description |\n|-------------|-------------|\n| \\`file:///workspace\\` | List files in working directory |\n| \\`file://{path}\\` | Read any file by path |\n| \\`db://index\\` | List all database keys |\n| \\`db://{namespace}/{key}\\` | Fetch a specific record |\n| \\`config://environment\\` | Safe environment info |\n| \\`config://package\\` | Package.json info |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\nAdd to your Claude Desktop config:\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Connecting a Real Database\n\nReplace the in-memory store in \\`src/resources/database.ts\\` with your actual data source:\n\n\\`\\`\\`typescript\n// Example with SQLite\nimport Database from 'better-sqlite3';\nconst db = new Database('./data.db');\n\n// Example with Postgres\nimport { Pool } from 'pg';\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL });\n\\`\\`\\`\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generatePromptServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { codeReviewPrompts } from './prompts/codeReview.js';\nimport { documentationPrompts } from './prompts/documentation.js';\nimport { debuggingPrompts } from './prompts/debugging.js';\nimport { refactoringPrompts } from './prompts/refactoring.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register prompt collections\ncodeReviewPrompts.register(server);\ndocumentationPrompts.register(server);\ndebuggingPrompts.register(server);\nrefactoringPrompts.register(server);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP prompt server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/prompts/codeReview.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Code review prompt templates.\n * Structured prompts that guide thorough, consistent code reviews.\n */\nexport const codeReviewPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'code-review',\n 'Comprehensive code review with focus areas',\n {\n code: z.string().describe('The code to review'),\n language: z.string().optional().describe('Programming language (e.g. TypeScript, Python)'),\n context: z.string().optional().describe('What does this code do? Any relevant context?'),\n focus: z.enum(['security', 'performance', 'readability', 'correctness', 'all'])\n .optional()\n .default('all')\n .describe('Area to focus the review on'),\n },\n ({ code, language, context, focus }) => {\n const lang = language ?? 'unknown';\n const focusInstructions: Record<string, string> = {\n security: \\`Focus specifically on security vulnerabilities:\n- Input validation and sanitization\n- Authentication and authorization flaws\n- Injection vulnerabilities (SQL, XSS, command)\n- Sensitive data exposure\n- Insecure dependencies\\`,\n performance: \\`Focus specifically on performance:\n- Time complexity of algorithms (Big O)\n- Unnecessary re-renders or recomputations\n- Memory leaks or excessive allocations\n- N+1 query problems\n- Missing indexes or caching opportunities\\`,\n readability: \\`Focus specifically on readability and maintainability:\n- Naming clarity (variables, functions, classes)\n- Function/method length and single responsibility\n- Comment quality (explain why, not what)\n- Consistent style and conventions\n- Dead code or confusing abstractions\\`,\n correctness: \\`Focus specifically on correctness:\n- Edge cases and boundary conditions\n- Error handling completeness\n- Race conditions or concurrency issues\n- Incorrect assumptions in logic\n- Missing null/undefined checks\\`,\n all: \\`Review all aspects: security, performance, readability, correctness, and design.\\`,\n };\n \n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Please perform a detailed code review of the following \\${lang} code.\n\n\\${context ? \\`Context: \\${context}\\\\n\\\\n\\` : ''}\\${focusInstructions[focus ?? 'all']}\n\nFor each issue found:\n1. Quote the specific code\n2. Explain the problem\n3. Provide a concrete fix\n\nRate severity as: 🔴 Critical | 🟠 High | 🟡 Medium | 🔵 Low | 💡 Suggestion\n\nCode to review:\n\\\\\\`\\\\\\`\\\\\\`\\${lang}\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'security-audit',\n 'Security-focused code audit',\n {\n code: z.string().describe('Code to audit'),\n threat_model: z.string().optional().describe('Who are the potential attackers? What are they after?'),\n },\n ({ code, threat_model }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Perform a security audit on this code.\n\n\\${threat_model ? \\`Threat model: \\${threat_model}\\\\n\\\\n\\` : ''}\nCheck for:\n- OWASP Top 10 vulnerabilities\n- Authentication/authorization bypasses\n- Data validation and sanitization\n- Cryptographic weaknesses\n- Dependency vulnerabilities\n- Secrets or credentials in code\n- Information disclosure\n\nFor each finding, provide:\n- CVE category (if applicable)\n- Severity (Critical/High/Medium/Low)\n- Attack vector\n- Remediation steps\n\nCode:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/documentation.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Documentation generation prompts.\n */\nexport const documentationPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'generate-docs',\n 'Generate comprehensive documentation for code',\n {\n code: z.string().describe('Code to document'),\n style: z.enum(['jsdoc', 'tsdoc', 'docstring', 'markdown']).optional().default('tsdoc'),\n audience: z.enum(['internal', 'public-api', 'tutorial']).optional().default('public-api'),\n },\n ({ code, style, audience }) => {\n const styleGuides: Record<string, string> = {\n jsdoc: 'Use JSDoc format with @param, @returns, @throws, @example tags',\n tsdoc: 'Use TSDoc format with @param, @returns, @throws, @example, @remarks tags',\n docstring: 'Use Python docstring format (Google style)',\n markdown: 'Generate a Markdown documentation section',\n };\n \n const audienceGuides: Record<string, string> = {\n internal: 'This is for internal developers. Focus on implementation details and gotchas.',\n 'public-api': 'This is a public API. Focus on usage, parameters, and examples. Hide implementation details.',\n tutorial: 'This is for beginners. Explain concepts, provide step-by-step examples.',\n };\n \n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Generate documentation for the following code.\n\nFormat: \\${styleGuides[style ?? 'tsdoc']}\nAudience: \\${audienceGuides[audience ?? 'public-api']}\n\nInclude:\n- Overview/description\n- Parameter documentation with types\n- Return value documentation\n- Thrown errors/exceptions\n- At least one usage example\n- Any important notes or caveats\n\nCode:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'readme-generator',\n 'Generate a README.md for a project',\n {\n project_name: z.string().describe('Project name'),\n description: z.string().describe('What does this project do?'),\n tech_stack: z.string().describe('Technologies used (e.g. Node.js, TypeScript, React)'),\n main_features: z.string().describe('Key features, one per line'),\n },\n ({ project_name, description, tech_stack, main_features }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Generate a professional README.md for this project.\n\nProject: \\${project_name}\nDescription: \\${description}\nTech Stack: \\${tech_stack}\nFeatures:\n\\${main_features}\n\nInclude these sections:\n1. Title and badges (placeholder)\n2. Description\n3. Features list\n4. Installation\n5. Quick start / usage example\n6. API reference (if applicable)\n7. Configuration\n8. Contributing\n9. License\n\nMake it clear, engaging, and developer-friendly.\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/debugging.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Debugging assistance prompts.\n */\nexport const debuggingPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'debug-error',\n 'Debug an error with full context analysis',\n {\n error_message: z.string().describe('The error message or stack trace'),\n code: z.string().optional().describe('Relevant code where the error occurs'),\n expected: z.string().optional().describe('What you expected to happen'),\n actual: z.string().optional().describe('What actually happened'),\n environment: z.string().optional().describe('Runtime environment (e.g. Node 18, Chrome 120)'),\n },\n ({ error_message, code, expected, actual, environment }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Help me debug this error.\n\nError:\n\\\\\\`\\\\\\`\\\\\\`\n\\${error_message}\n\\\\\\`\\\\\\`\\\\\\`\n\\${code ? \\`\\\\nRelevant code:\\\\n\\\\\\`\\\\\\`\\\\\\`\\\\n\\${code}\\\\n\\\\\\`\\\\\\`\\\\\\`\\` : ''}\n\\${expected ? \\`\\\\nExpected: \\${expected}\\` : ''}\n\\${actual ? \\`\\\\nActual: \\${actual}\\` : ''}\n\\${environment ? \\`\\\\nEnvironment: \\${environment}\\` : ''}\n\nPlease:\n1. Identify the root cause\n2. Explain why this error occurs\n3. Provide a step-by-step fix\n4. Suggest how to prevent this in the future\\`,\n },\n },\n ],\n }),\n );\n\n server.prompt(\n 'rubber-duck',\n 'Explain code logic to find bugs through explanation',\n {\n code: z.string().describe('Code you want to explain/debug'),\n problem: z.string().describe('What problem are you trying to solve with this code?'),\n },\n ({ code, problem }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`I'll explain my code to you and you help me find bugs through questioning.\n\nProblem I'm trying to solve: \\${problem}\n\nMy code:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nAs I explain my code, please:\n1. Ask clarifying questions about assumptions I'm making\n2. Point out any logical inconsistencies\n3. Highlight edge cases I might not be handling\n4. Don't give me the answer directly — help me discover it through questions\n\nLet's start: what questions do you have about my approach?\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/refactoring.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Code refactoring prompts.\n */\nexport const refactoringPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'refactor',\n 'Refactor code with specific goals',\n {\n code: z.string().describe('Code to refactor'),\n goals: z.string().describe('What do you want to improve? (e.g. reduce complexity, improve testability)'),\n constraints: z.string().optional().describe('Any constraints (e.g. must keep same API, cannot use classes)'),\n language: z.string().optional().describe('Programming language'),\n },\n ({ code, goals, constraints, language }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Refactor this \\${language ?? ''} code to achieve the following goals:\n\nGoals: \\${goals}\n\\${constraints ? \\`Constraints: \\${constraints}\\` : ''}\n\nOriginal code:\n\\\\\\`\\\\\\`\\\\\\`\\${language ?? ''}\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nPlease:\n1. Explain your refactoring strategy\n2. Provide the refactored code\n3. Highlight what changed and why\n4. Note any tradeoffs\\`,\n },\n },\n ],\n }),\n );\n\n server.prompt(\n 'extract-function',\n 'Extract logic into well-named functions',\n {\n code: z.string().describe('Code containing logic to extract'),\n description: z.string().describe('Describe the logic you want to extract'),\n },\n ({ code, description }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Help me extract the following logic into a well-named function:\n\nLogic to extract: \\${description}\n\nFrom this code:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nPlease provide:\n1. The extracted function with a clear, descriptive name\n2. The modified original code calling the new function\n3. Any parameters the function needs\n4. Proper TypeScript types if applicable\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n zod: '^3.22.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) prompt server that provides structured, high-quality prompts for software development tasks.\n\n## Prompts\n\n### Code Review\n| Prompt | Description |\n|--------|-------------|\n| \\`code-review\\` | Comprehensive review with severity ratings |\n| \\`security-audit\\` | Security-focused code audit |\n\n### Documentation \n| Prompt | Description |\n|--------|-------------|\n| \\`generate-docs\\` | Generate JSDoc/TSDoc/docstrings |\n| \\`readme-generator\\` | Generate a full README.md |\n\n### Debugging\n| Prompt | Description |\n|--------|-------------|\n| \\`debug-error\\` | Debug errors with full context |\n| \\`rubber-duck\\` | Guided explanation-based debugging |\n\n### Refactoring\n| Prompt | Description |\n|--------|-------------|\n| \\`refactor\\` | Refactor with specific goals and constraints |\n| \\`extract-function\\` | Extract logic into named functions |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Adding Prompts\n\nCreate a new file in \\`src/prompts/\\` and register it in \\`src/index.ts\\`:\n\n\\`\\`\\`typescript\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nexport const myPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'my-prompt-name',\n 'Description of what this prompt does',\n {\n input: z.string().describe('User input'),\n },\n ({ input }) => ({\n messages: [\n {\n role: 'user',\n content: { type: 'text', text: \\`Do something with: \\${input}\\` },\n },\n ],\n }),\n );\n },\n};\n\\`\\`\\`\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,OAAOA,YAAW;;;ACDlB,OAAOC,WAAU;AACjB,OAAOC,YAAW;AAClB,OAAO,SAAS;AAChB,OAAOC,SAAQ;;;ACHf,OAAO,cAAc;AAYrB,eAAsB,UAAU,UAA2D;AACzF,SAAO,SAAS,OAAsB;AAAA,IACpC;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,UAAU,cAAc;AAAA,MACjC,UAAU,CAAC,UAAkB;AAC3B,YAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,YAAI,CAAC,eAAe,KAAK,KAAK,EAAG,QAAO;AACxC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,UAAU,qBAAqB;AAAA,IAC1C;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,UAAU,YAAY;AAAA,MAC/B,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,CAAC,YAA2B,UAAU,eAAe,QAAQ;AAAA,MACtE,UAAU,CAAC,UAAkB;AAC3B,YAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,UAAU,UAAU;AAAA,IAC/B;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,UAAU,WAAW;AAAA,IAChC;AAAA,EACF,CAAC;AACH;AAEO,SAAS,mBACd,WACA,SACA,YAAmC,CAAC,GACtB;AACd,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,GAAG;AAAA,EACL;AACF;;;ACjGA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,WAAW;AAGlB,eAAsB,WACpB,WACA,OACA,OACwB;AACxB,QAAM,UAAyB,CAAC;AAEhC,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,KAAK,WAAW,KAAK,IAAI;AAE/C,QAAI,KAAK,aAAa;AACpB,YAAM,GAAG,UAAU,QAAQ;AAC3B,cAAQ,KAAK,EAAE,MAAM,KAAK,MAAM,QAAQ,UAAU,CAAC;AACnD;AAAA,IACF;AAEA,UAAM,GAAG,UAAU,KAAK,QAAQ,QAAQ,CAAC;AAEzC,UAAM,SAAS,MAAM,GAAG,WAAW,QAAQ;AAE3C,QAAI,UAAU,CAAC,OAAO;AACpB,cAAQ,KAAK,EAAE,MAAM,KAAK,MAAM,QAAQ,UAAU,CAAC;AACnD;AAAA,IACF;AAEA,UAAM,GAAG,UAAU,UAAU,KAAK,SAAS,MAAM;AACjD,YAAQ,KAAK,EAAE,MAAM,KAAK,MAAM,QAAQ,SAAS,gBAAgB,UAAU,CAAC;AAAA,EAC9E;AAEA,SAAO;AACT;AAEO,SAAS,gBAAgB,WAAmB,OAA8B;AAC/E,UAAQ,IAAI,MAAM,KAAK,aAAM,SAAS,GAAG,CAAC;AAC1C,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,cAAc,cAAO;AACvC,YAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,EACjD;AACA,UAAQ,IAAI;AACd;AAEO,SAAS,kBAAkB,SAA8B;AAC9D,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,WAAW,WAAW;AAC/B,cAAQ,IAAI,KAAK,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO,IAAI,EAAE;AAAA,IACpD,WAAW,OAAO,WAAW,eAAe;AAC1C,cAAQ,IAAI,KAAK,MAAM,OAAO,GAAG,CAAC,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,eAAe,CAAC,EAAE;AAAA,IACnF,OAAO;AACL,cAAQ,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,WAAW,CAAC,EAAE;AAAA,IAC5E;AAAA,EACF;AACF;;;ACtDO,SAAS,mBAAmB,QAAuC;AACxE,QAAM,EAAE,YAAY,mBAAmB,aAAa,OAAO,IAAI;AAE/D,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WASJ,UAAU;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,mBAoCF,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQzB;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqDX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqDX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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,IAyEX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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,IAwEX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS,KAAK,UAAU;AAAA,QACtB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa;AAAA,QACb,MAAM;AAAA,QACN,SAAS;AAAA,UACP,OAAO;AAAA,UACP,KAAK;AAAA,UACL,OAAO;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,SAAS,EAAE,MAAM,WAAW;AAAA,QAC5B,cAAc;AAAA,UACZ,6BAA6B;AAAA,UAC7B,KAAK;AAAA,QACP;AAAA,QACA,iBAAiB;AAAA,UACf,eAAe;AAAA,UACf,YAAY;AAAA,QACd;AAAA,MACF,GAAG,MAAM,CAAC;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS,KAAK,UAAU;AAAA,QACtB,iBAAiB;AAAA,UACf,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,kBAAkB;AAAA,UAClB,KAAK,CAAC,QAAQ;AAAA,UACd,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,iBAAiB;AAAA,UACjB,cAAc;AAAA,UACd,aAAa;AAAA,UACb,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,SAAS,CAAC,UAAU;AAAA,QACpB,SAAS,CAAC,gBAAgB,MAAM;AAAA,MAClC,GAAG,MAAM,CAAC;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS,KAAK,UAAU;AAAA;AAAA,EAE5B,iBAAiB;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,OA2BZ,UAAU;AAAA;AAAA,kBAEC,OAAO,SAAS;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,EAwChC,MAAM;AAAA;AAAA,IAEJ;AAAA,EACF;AACF;;;ACzcO,SAAS,uBAAuB,QAAuC;AAC5E,QAAM,EAAE,YAAY,mBAAmB,aAAa,OAAO,IAAI;AAE/D,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAOJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAYF,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQzB;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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;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,IAwHX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA2DX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA0HX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAuGX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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,IAmFX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["chalk","path","chalk","fs","path","chalk","fs","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/utils/prompts.ts","../src/utils/files.ts","../src/templates/tool-server.ts","../src/templates/resource-server.ts","../src/templates/prompt-server.ts","../src/commands/add.ts"],"sourcesContent":["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\nimport { addCommand } from './commands/add.js';\n\nconst VERSION = '0.2.0';\n\nconst program = new Command();\n\nprogram\n .name('create-mcp-server')\n .description('Scaffold production-ready MCP (Model Context Protocol) servers')\n .version(VERSION, '-v, --version', 'Show version')\n .addHelpText(\n 'after',\n `\n${chalk.bold('Examples:')}\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server')} Scaffold with prompts\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server --yes')} Use all defaults (tool-server)\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server -t resource-server')} Use resource-server template\n ${chalk.cyan('npx @webbywisp/create-mcp-server my-server --dry-run')} Preview without writing files\n\n${chalk.bold('Templates:')}\n ${chalk.cyan('tool-server')} Expose tools (functions AI can call) — file I/O, HTTP, exec\n ${chalk.cyan('resource-server')} Expose data as addressable URIs — files, DB, config\n ${chalk.cyan('prompt-server')} Provide structured prompt templates — review, debug, refactor\n`,\n );\n\n// ─── init command (default) ───────────────────────────────────────────────────\n\nprogram\n .command('init [directory]', { isDefault: true })\n .description('Scaffold a new MCP server (default command)')\n .option('-t, --template <name>', 'Template: tool-server | resource-server | prompt-server', 'tool-server')\n .option('-y, --yes', 'Skip prompts, use all defaults')\n .option('--dry-run', 'Preview what would be created without writing files')\n .option('--force', 'Overwrite existing files')\n .action(async (dir: string | undefined, opts) => {\n try {\n await initCommand(dir, {\n template: opts.template,\n yes: opts.yes,\n dryRun: opts.dryRun,\n force: opts.force,\n });\n } catch (err) {\n handleError(err);\n }\n });\n\n// ─── add command ─────────────────────────────────────────────────────────────\n\nprogram\n .command('add [type] [name]')\n .description('Add a tool, resource, or prompt to an existing server')\n .addHelpText(\n 'after',\n `\n${chalk.bold('Types:')}\n ${chalk.cyan('tool')} Add a new tool file (callable function)\n ${chalk.cyan('resource')} Add a new resource provider (addressable URI)\n ${chalk.cyan('prompt')} Add a new prompt template\n\n${chalk.bold('Examples:')}\n ${chalk.cyan('create-mcp-server add tool github-search')}\n ${chalk.cyan('create-mcp-server add resource postgres-db')}\n ${chalk.cyan('create-mcp-server add prompt summarize --dry-run')}\n`,\n )\n .option('--force', 'Overwrite existing files')\n .option('--dry-run', 'Preview without writing')\n .action(async (type: string | undefined, name: string | undefined, opts) => {\n try {\n await addCommand(type, name, {\n force: opts.force,\n dryRun: opts.dryRun,\n });\n } catch (err) {\n handleError(err);\n }\n });\n\n// ─── list command ─────────────────────────────────────────────────────────────\n\nprogram\n .command('list')\n .description('Show available templates')\n .action(() => {\n console.log();\n console.log(chalk.bold('Available Templates:'));\n console.log();\n\n const templates = [\n {\n name: 'tool-server',\n desc: 'Expose callable tools to AI models',\n includes: 'read_file, write_file, http_fetch, exec_command',\n },\n {\n name: 'resource-server',\n desc: 'Expose data as addressable resources',\n includes: 'file://, db://, config:// URI schemes',\n },\n {\n name: 'prompt-server',\n desc: 'Provide structured prompt templates',\n includes: 'code-review, debug-error, generate-docs, refactor',\n },\n ];\n\n templates.forEach(({ name, desc, includes }) => {\n console.log(` ${chalk.cyan.bold(name.padEnd(18))} ${desc}`);\n console.log(` ${' '.repeat(18)} ${chalk.dim('Includes: ' + includes)}`);\n console.log();\n });\n });\n\n// ─── Error handler ─────────────────────────────────────────────────────────\n\nfunction handleError(err: unknown): void {\n if (err instanceof Error) {\n console.error(chalk.red(`\\n❌ Error: ${err.message}`));\n if (process.env.DEBUG) {\n console.error(chalk.dim(err.stack ?? ''));\n }\n } else {\n console.error(chalk.red('\\n❌ An unexpected error occurred'));\n console.error(err);\n }\n process.exit(1);\n}\n\n// ─── Parse ─────────────────────────────────────────────────────────────────\n\nprogram.parseAsync(process.argv).catch(handleError);\n","import path from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport fs from 'fs-extra';\n\nimport type { ServerConfig, Template } from '../types.js';\nimport { runWizard, buildDefaultConfig } from '../utils/prompts.js';\nimport { writeFiles, printDryRunTree, printWriteResults } from '../utils/files.js';\nimport { generateToolServer } from '../templates/tool-server.js';\nimport { generateResourceServer } from '../templates/resource-server.js';\nimport { generatePromptServer } from '../templates/prompt-server.js';\nimport type { GeneratedFile } from '../types.js';\n\nexport interface InitOptions {\n template?: string;\n yes?: boolean;\n dryRun?: boolean;\n force?: boolean;\n}\n\nexport async function initCommand(dirArg: string | undefined, opts: InitOptions): Promise<void> {\n const targetName = dirArg ?? '.';\n const targetDir = path.resolve(process.cwd(), targetName);\n const dirName = path.basename(targetDir);\n\n console.log();\n console.log(chalk.bold.cyan('⚡ create-mcp-server') + chalk.dim(' — scaffold your MCP server'));\n console.log();\n\n // Check existing directory\n const targetExists = await fs.pathExists(targetDir);\n if (targetExists && !opts.dryRun) {\n const entries = await fs.readdir(targetDir).catch(() => []);\n const hasContent = entries.some((e: string) => !e.startsWith('.'));\n if (hasContent && !opts.force) {\n console.log(chalk.yellow(`⚠️ Directory ${chalk.bold(targetDir)} already has files.`));\n console.log(chalk.dim(' Existing files will be skipped. Use --force to overwrite.'));\n console.log();\n }\n }\n\n // Gather config\n let config: ServerConfig;\n const isInteractive = !opts.yes && process.stdin.isTTY;\n\n if (isInteractive) {\n const answers = await runWizard({\n serverName: dirName !== '.' ? dirName : undefined,\n template: opts.template as Template | undefined,\n });\n\n config = buildDefaultConfig(targetDir, dirName, {\n serverName: answers.serverName,\n serverDescription: answers.serverDescription,\n template: answers.template,\n packageName: answers.packageName,\n author: answers.author,\n gitInit: answers.gitInit,\n dryRun: opts.dryRun ?? false,\n });\n } else {\n config = buildDefaultConfig(targetDir, dirName, {\n serverName: dirName !== '.' ? dirName : 'my-mcp-server',\n packageName: dirName !== '.' ? dirName : 'my-mcp-server',\n template: (opts.template as Template) ?? 'tool-server',\n dryRun: opts.dryRun ?? false,\n yes: true,\n });\n console.log(chalk.dim(`Running with defaults. Template: ${config.template}`));\n console.log();\n }\n\n // Generate files\n const files = getTemplateFiles(config);\n\n // Dry run\n if (config.dryRun) {\n console.log(chalk.bold.yellow('🔍 Dry run — no files will be written\\n'));\n printDryRunTree(config.targetDir, files);\n console.log(chalk.dim(` ${files.length} files would be created`));\n console.log();\n console.log(chalk.dim('Run without --dry-run to scaffold the server.'));\n return;\n }\n\n // Write files\n const spinner = ora('Scaffolding MCP server...').start();\n let results;\n\n try {\n results = await writeFiles(config.targetDir, files, opts.force ?? false);\n spinner.succeed('Server scaffolded');\n } catch (err) {\n spinner.fail('Failed to write files');\n throw err;\n }\n\n // Git init\n if (config.gitInit) {\n const gitSpinner = ora('Initializing git...').start();\n try {\n const { simpleGit } = await import('simple-git');\n const git = simpleGit(config.targetDir);\n const isRepo = await git.checkIsRepo().catch(() => false);\n if (!isRepo) {\n await git.init();\n gitSpinner.succeed('Git repository initialized');\n } else {\n gitSpinner.info('Git already initialized, skipped');\n }\n } catch {\n gitSpinner.warn('Git init failed (git may not be installed)');\n }\n }\n\n // Summary\n const created = results.filter((r) => r.status === 'created');\n const skipped = results.filter((r) => r.status === 'skipped');\n\n console.log();\n console.log(chalk.bold.green('✅ MCP server scaffolded at ') + chalk.bold(config.targetDir));\n console.log();\n printWriteResults(results);\n\n console.log();\n console.log(chalk.dim(` ${created.length} file(s) created${skipped.length > 0 ? `, ${skipped.length} skipped` : ''}`));\n\n // Next steps\n console.log();\n console.log(chalk.bold('Next steps:'));\n\n const rel = path.relative(process.cwd(), config.targetDir);\n if (rel && rel !== '.') {\n console.log(` ${chalk.cyan(`cd ${rel}`)}`);\n }\n console.log(` ${chalk.cyan('npm install')}`);\n console.log(` ${chalk.cyan('npm run build')}`);\n console.log(` ${chalk.cyan('npm start')}`);\n console.log();\n console.log(chalk.dim(' Then add to Claude Desktop config:'));\n console.log(chalk.dim(` \"command\": \"node\", \"args\": [\"${config.targetDir}/dist/index.js\"]`));\n console.log();\n console.log(chalk.dim(' See README.md for full setup instructions.'));\n console.log();\n}\n\nfunction getTemplateFiles(config: ServerConfig): GeneratedFile[] {\n switch (config.template) {\n case 'tool-server':\n return generateToolServer(config);\n case 'resource-server':\n return generateResourceServer(config);\n case 'prompt-server':\n return generatePromptServer(config);\n default:\n return generateToolServer(config);\n }\n}\n","import inquirer from 'inquirer';\nimport type { ServerConfig, Template } from '../types.js';\n\nexport interface WizardAnswers {\n serverName: string;\n serverDescription: string;\n template: Template;\n packageName: string;\n author: string;\n gitInit: boolean;\n}\n\nexport async function runWizard(defaults?: Partial<WizardAnswers>): Promise<WizardAnswers> {\n return inquirer.prompt<WizardAnswers>([\n {\n type: 'input',\n name: 'serverName',\n message: 'Server name (used in MCP config):',\n default: defaults?.serverName ?? 'my-mcp-server',\n validate: (input: string) => {\n if (!input.trim()) return 'Server name cannot be empty';\n if (!/^[a-z0-9-]+$/.test(input)) return 'Use lowercase letters, numbers, and hyphens only';\n return true;\n },\n },\n {\n type: 'input',\n name: 'serverDescription',\n message: 'Short description:',\n default: defaults?.serverDescription ?? 'An MCP server',\n },\n {\n type: 'list',\n name: 'template',\n message: 'Choose a template:',\n default: defaults?.template ?? 'tool-server',\n choices: [\n {\n name: 'tool-server — expose tools (functions AI can call)',\n value: 'tool-server',\n short: 'tool-server',\n },\n {\n name: 'resource-server — expose data/files as addressable resources',\n value: 'resource-server',\n short: 'resource-server',\n },\n {\n name: 'prompt-server — provide structured prompt templates',\n value: 'prompt-server',\n short: 'prompt-server',\n },\n ],\n },\n {\n type: 'input',\n name: 'packageName',\n message: 'npm package name:',\n default: (answers: WizardAnswers) => defaults?.packageName ?? answers.serverName,\n validate: (input: string) => {\n if (!input.trim()) return 'Package name cannot be empty';\n return true;\n },\n },\n {\n type: 'input',\n name: 'author',\n message: 'Author name:',\n default: defaults?.author ?? '',\n },\n {\n type: 'confirm',\n name: 'gitInit',\n message: 'Initialize a git repository?',\n default: defaults?.gitInit ?? true,\n },\n ]);\n}\n\nexport function buildDefaultConfig(\n targetDir: string,\n dirName: string,\n overrides: Partial<ServerConfig> = {},\n): ServerConfig {\n return {\n targetDir,\n dirName,\n serverName: dirName,\n serverDescription: `An MCP server`,\n template: 'tool-server',\n packageName: dirName,\n author: '',\n gitInit: true,\n dryRun: false,\n yes: false,\n ...overrides,\n };\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport chalk from 'chalk';\nimport type { GeneratedFile, WriteResult } from '../types.js';\n\nexport async function writeFiles(\n targetDir: string,\n files: GeneratedFile[],\n force: boolean,\n): Promise<WriteResult[]> {\n const results: WriteResult[] = [];\n\n for (const file of files) {\n const filePath = path.join(targetDir, file.path);\n\n if (file.isDirectory) {\n await fs.ensureDir(filePath);\n results.push({ path: file.path, status: 'created' });\n continue;\n }\n\n await fs.ensureDir(path.dirname(filePath));\n\n const exists = await fs.pathExists(filePath);\n\n if (exists && !force) {\n results.push({ path: file.path, status: 'skipped' });\n continue;\n }\n\n await fs.writeFile(filePath, file.content, 'utf8');\n results.push({ path: file.path, status: exists ? 'overwritten' : 'created' });\n }\n\n return results;\n}\n\nexport function printDryRunTree(targetDir: string, files: GeneratedFile[]): void {\n console.log(chalk.bold(`📁 ${targetDir}/`));\n for (const file of files) {\n const icon = file.isDirectory ? '📁' : '📄';\n console.log(chalk.dim(` ${icon} ${file.path}`));\n }\n console.log();\n}\n\nexport function printWriteResults(results: WriteResult[]): void {\n for (const result of results) {\n if (result.status === 'created') {\n console.log(` ${chalk.green('+')} ${result.path}`);\n } else if (result.status === 'overwritten') {\n console.log(` ${chalk.yellow('~')} ${result.path} ${chalk.dim('(overwritten)')}`);\n } else {\n console.log(` ${chalk.dim('-')} ${result.path} ${chalk.dim('(skipped)')}`);\n }\n }\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generateToolServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { readFileTool } from './tools/readFile.js';\nimport { writeFileTool } from './tools/writeFile.js';\nimport { httpFetchTool } from './tools/httpFetch.js';\nimport { execCommandTool } from './tools/execCommand.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register all tools\nserver.tool(\n readFileTool.name,\n readFileTool.description,\n readFileTool.inputSchema,\n readFileTool.handler,\n);\n\nserver.tool(\n writeFileTool.name,\n writeFileTool.description,\n writeFileTool.inputSchema,\n writeFileTool.handler,\n);\n\nserver.tool(\n httpFetchTool.name,\n httpFetchTool.description,\n httpFetchTool.inputSchema,\n httpFetchTool.handler,\n);\n\nserver.tool(\n execCommandTool.name,\n execCommandTool.description,\n execCommandTool.inputSchema,\n execCommandTool.handler,\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/tools/readFile.ts',\n content: `import { z } from 'zod';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const readFileTool = {\n name: 'read_file',\n description: 'Read the contents of a file. Returns the file content as a string.',\n inputSchema: {\n path: z.string().describe('Absolute or relative path to the file'),\n encoding: z.enum(['utf8', 'base64']).optional().default('utf8').describe('File encoding'),\n maxBytes: z.number().optional().default(1048576).describe('Max bytes to read (default 1MB)'),\n },\n handler: async ({ path: filePath, encoding, maxBytes }: {\n path: string;\n encoding?: 'utf8' | 'base64';\n maxBytes?: number;\n }) => {\n const resolvedPath = path.resolve(filePath);\n \n try {\n const stat = await fs.stat(resolvedPath);\n \n if (!stat.isFile()) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: \\${filePath} is not a file\\` }],\n isError: true,\n };\n }\n \n if (stat.size > (maxBytes ?? 1048576)) {\n return {\n content: [{ \n type: 'text' as const, \n text: \\`Error: File too large (\\${stat.size} bytes). Max is \\${maxBytes} bytes.\\` \n }],\n isError: true,\n };\n }\n \n const content = await fs.readFile(resolvedPath, encoding ?? 'utf8');\n \n return {\n content: [{ type: 'text' as const, text: String(content) }],\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`Error reading file: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/writeFile.ts',\n content: `import { z } from 'zod';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const writeFileTool = {\n name: 'write_file',\n description: 'Write content to a file. Creates parent directories if needed.',\n inputSchema: {\n path: z.string().describe('Absolute or relative path to write to'),\n content: z.string().describe('Content to write'),\n encoding: z.enum(['utf8', 'base64']).optional().default('utf8').describe('File encoding'),\n createDirs: z.boolean().optional().default(true).describe('Create parent directories if missing'),\n overwrite: z.boolean().optional().default(true).describe('Overwrite if file exists'),\n },\n handler: async ({ path: filePath, content, encoding, createDirs, overwrite }: {\n path: string;\n content: string;\n encoding?: 'utf8' | 'base64';\n createDirs?: boolean;\n overwrite?: boolean;\n }) => {\n const resolvedPath = path.resolve(filePath);\n \n try {\n // Check if file exists\n if (!overwrite) {\n const exists = await fs.access(resolvedPath).then(() => true).catch(() => false);\n if (exists) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: File already exists at \\${filePath}. Set overwrite=true to overwrite.\\` }],\n isError: true,\n };\n }\n }\n \n if (createDirs) {\n await fs.mkdir(path.dirname(resolvedPath), { recursive: true });\n }\n \n await fs.writeFile(resolvedPath, content, encoding ?? 'utf8');\n \n return {\n content: [{ type: 'text' as const, text: \\`Successfully wrote \\${content.length} bytes to \\${filePath}\\` }],\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`Error writing file: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/httpFetch.ts',\n content: `import { z } from 'zod';\n\nexport const httpFetchTool = {\n name: 'http_fetch',\n description: 'Make an HTTP request and return the response. Supports GET, POST, PUT, DELETE.',\n inputSchema: {\n url: z.string().url().describe('URL to fetch'),\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).optional().default('GET').describe('HTTP method'),\n headers: z.record(z.string()).optional().describe('Request headers as key-value pairs'),\n body: z.string().optional().describe('Request body (for POST/PUT/PATCH)'),\n timeoutMs: z.number().optional().default(30000).describe('Timeout in milliseconds'),\n maxBytes: z.number().optional().default(524288).describe('Max response bytes (default 512KB)'),\n },\n handler: async ({ url, method, headers, body, timeoutMs, maxBytes }: {\n url: string;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeoutMs?: number;\n maxBytes?: number;\n }) => {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs ?? 30000);\n \n const response = await fetch(url, {\n method: method ?? 'GET',\n headers: headers,\n body: body,\n signal: controller.signal,\n });\n \n clearTimeout(timeout);\n \n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n \n const contentType = response.headers.get('content-type') ?? '';\n let responseText: string;\n \n if (contentType.includes('application/json') || contentType.includes('text/')) {\n const arrayBuffer = await response.arrayBuffer();\n const bytes = arrayBuffer.byteLength;\n if (bytes > (maxBytes ?? 524288)) {\n responseText = \\`[Response truncated: \\${bytes} bytes exceeds maxBytes limit]\\`;\n } else {\n responseText = new TextDecoder().decode(arrayBuffer);\n }\n } else {\n responseText = \\`[Binary content: \\${contentType}]\\`;\n }\n \n const summary = [\n \\`Status: \\${response.status} \\${response.statusText}\\`,\n \\`Content-Type: \\${contentType}\\`,\n \\`\\\\n\\${responseText}\\`,\n ].join('\\\\n');\n \n return {\n content: [{ type: 'text' as const, text: summary }],\n isError: !response.ok,\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`HTTP request failed: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'src/tools/execCommand.ts',\n content: `import { z } from 'zod';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n// Safety: block dangerous commands by default\nconst BLOCKED_PATTERNS = [\n /rm\\\\s+-rf\\\\s+\\\\//,\n /mkfs/,\n /dd\\\\s+if=/,\n /:(\\\\s*)\\\\{\\\\s*:\\\\|:&\\\\s*\\\\}/, // fork bomb\n />\\\\/dev\\\\/(sd|hd|nvme)/,\n];\n\nexport const execCommandTool = {\n name: 'exec_command',\n description: 'Execute a shell command and return stdout/stderr. Use with caution.',\n inputSchema: {\n command: z.string().describe('Shell command to execute'),\n cwd: z.string().optional().describe('Working directory (defaults to process cwd)'),\n timeoutMs: z.number().optional().default(30000).describe('Timeout in milliseconds'),\n env: z.record(z.string()).optional().describe('Additional environment variables'),\n },\n handler: async ({ command, cwd, timeoutMs, env }: {\n command: string;\n cwd?: string;\n timeoutMs?: number;\n env?: Record<string, string>;\n }) => {\n // Safety check\n for (const pattern of BLOCKED_PATTERNS) {\n if (pattern.test(command)) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: Command blocked for safety: \\${command}\\` }],\n isError: true,\n };\n }\n }\n \n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: cwd ?? process.cwd(),\n timeout: timeoutMs ?? 30000,\n env: { ...process.env, ...env },\n maxBuffer: 1024 * 1024, // 1MB\n });\n \n const output = [\n stdout && \\`stdout:\\\\n\\${stdout.trim()}\\`,\n stderr && \\`stderr:\\\\n\\${stderr.trim()}\\`,\n ].filter(Boolean).join('\\\\n\\\\n') || '(no output)';\n \n return {\n content: [{ type: 'text' as const, text: output }],\n };\n } catch (err: any) {\n const output = [\n \\`Exit code: \\${err.code ?? 'unknown'}\\`,\n err.stdout && \\`stdout:\\\\n\\${err.stdout.trim()}\\`,\n err.stderr && \\`stderr:\\\\n\\${err.stderr.trim()}\\`,\n \\`Error: \\${err.message}\\`,\n ].filter(Boolean).join('\\\\n');\n \n return {\n content: [{ type: 'text' as const, text: output }],\n isError: true,\n };\n }\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n zod: '^3.22.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) tool server that exposes file system, HTTP, and shell execution capabilities to AI models.\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| \\`read_file\\` | Read file contents with encoding and size limits |\n| \\`write_file\\` | Write files, creating directories as needed |\n| \\`http_fetch\\` | Make HTTP requests (GET, POST, PUT, DELETE) |\n| \\`exec_command\\` | Execute shell commands with safety checks |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\nAdd to your Claude Desktop config (\\`~/Library/Application Support/Claude/claude_desktop_config.json\\`):\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Adding Tools\n\nCreate a new file in \\`src/tools/\\` following the existing pattern:\n\n\\`\\`\\`typescript\nimport { z } from 'zod';\n\nexport const myTool = {\n name: 'my_tool',\n description: 'Description of what this tool does',\n inputSchema: {\n param1: z.string().describe('First parameter'),\n param2: z.number().optional().describe('Optional number'),\n },\n handler: async ({ param1, param2 }) => {\n // Your implementation\n return {\n content: [{ type: 'text' as const, text: 'result' }],\n };\n },\n};\n\\`\\`\\`\n\nThen register it in \\`src/index.ts\\`.\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generateResourceServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { fileSystemResources } from './resources/fileSystem.js';\nimport { databaseResources } from './resources/database.js';\nimport { configResources } from './resources/config.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register resource providers\nfileSystemResources.register(server);\ndatabaseResources.register(server);\nconfigResources.register(server);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP resource server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/resources/fileSystem.ts',\n content: `import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport fs from 'fs/promises';\nimport path from 'path';\n\n/**\n * File system resources — expose files and directories as MCP resources.\n * URI pattern: file:///absolute/path/to/file\n */\nexport const fileSystemResources = {\n register(server: McpServer) {\n // Static resource: list files in a directory\n server.resource(\n 'workspace-files',\n 'file:///workspace',\n async (uri) => {\n const dir = process.cwd();\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n const listing = entries\n .map((e) => \\`\\${e.isDirectory() ? '[dir]' : '[file]'} \\${e.name}\\`)\n .join('\\\\n');\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: \\`Files in \\${dir}:\\\\n\\\\n\\${listing}\\`,\n }],\n };\n } catch (err: any) {\n throw new Error(\\`Failed to list directory: \\${err.message}\\`);\n }\n },\n );\n\n // Dynamic resource template: read any file by URI\n server.resource(\n 'file',\n new ResourceTemplate('file://{path}', { list: undefined }),\n async (uri, params) => {\n const filePath = decodeURIComponent(params.path as string);\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(process.cwd(), filePath);\n \n try {\n const stat = await fs.stat(resolvedPath);\n \n if (stat.isDirectory()) {\n const entries = await fs.readdir(resolvedPath, { withFileTypes: true });\n const listing = entries\n .map((e) => \\`\\${e.isDirectory() ? '[dir] ' : '[file]'} \\${e.name}\\`)\n .join('\\\\n');\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: listing,\n }],\n };\n }\n \n const ext = path.extname(resolvedPath).toLowerCase();\n const textExtensions = new Set([\n '.ts', '.tsx', '.js', '.jsx', '.json', '.md', '.txt', \n '.yaml', '.yml', '.toml', '.env', '.sh', '.bash', '.zsh',\n '.py', '.rb', '.go', '.rs', '.java', '.c', '.cpp', '.h',\n '.html', '.css', '.scss', '.less', '.xml', '.svg',\n ]);\n \n if (textExtensions.has(ext) || stat.size < 100000) {\n const content = await fs.readFile(resolvedPath, 'utf8');\n const mimeType = getMimeType(ext);\n \n return {\n contents: [{\n uri: uri.href,\n mimeType,\n text: content,\n }],\n };\n } else {\n const data = await fs.readFile(resolvedPath);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/octet-stream',\n blob: data.toString('base64'),\n }],\n };\n }\n } catch (err: any) {\n throw new Error(\\`Failed to read file \\${resolvedPath}: \\${err.message}\\`);\n }\n },\n );\n },\n};\n\nfunction getMimeType(ext: string): string {\n const map: Record<string, string> = {\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.js': 'text/javascript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.md': 'text/markdown',\n '.txt': 'text/plain',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.html': 'text/html',\n '.css': 'text/css',\n '.svg': 'image/svg+xml',\n '.xml': 'application/xml',\n '.py': 'text/x-python',\n '.sh': 'text/x-sh',\n };\n return map[ext] ?? 'text/plain';\n}\n`,\n },\n {\n path: 'src/resources/database.ts',\n content: `import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\n\n// Example: In-memory key-value store as a resource.\n// Replace with your actual data source (SQLite, Postgres, Redis, etc.)\nconst store = new Map<string, unknown>([\n ['example:config', { version: '1.0', feature_flags: { new_ui: true } }],\n ['example:stats', { requests: 0, errors: 0, uptime: Date.now() }],\n]);\n\n/**\n * Database/store resources — expose structured data as MCP resources.\n * URI pattern: db://namespace/key\n * \n * Replace the in-memory store with your actual database client.\n */\nexport const databaseResources = {\n register(server: McpServer) {\n // List all available keys\n server.resource(\n 'db-index',\n 'db://index',\n async (uri) => {\n const keys = Array.from(store.keys());\n const listing = keys.map(k => \\` \\${k}\\`).join('\\\\n');\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: \\`Available keys (\\${keys.length}):\\\\n\\${listing}\\`,\n }],\n };\n },\n );\n\n // Dynamic resource: fetch any key\n server.resource(\n 'db-record',\n new ResourceTemplate('db://{namespace}/{key}', { list: undefined }),\n async (uri, params) => {\n const recordKey = \\`\\${params.namespace}:\\${params.key}\\`;\n const value = store.get(recordKey);\n \n if (value === undefined) {\n throw new Error(\\`Key not found: \\${recordKey}\\`);\n }\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(value, null, 2),\n }],\n };\n },\n );\n },\n};\n`,\n },\n {\n path: 'src/resources/config.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport fs from 'fs/promises';\nimport path from 'path';\n\n/**\n * Config resources — expose runtime config, env vars, and app settings.\n * \n * These are useful for giving the AI context about the environment\n * without exposing sensitive credentials.\n */\nexport const configResources = {\n register(server: McpServer) {\n // Expose safe environment info\n server.resource(\n 'environment',\n 'config://environment',\n async (uri) => {\n const safeEnv: Record<string, string> = {};\n \n // Only expose non-sensitive env vars\n const allowedPrefixes = ['NODE_', 'npm_', 'PATH', 'HOME', 'USER', 'SHELL', 'LANG'];\n const blockedKeys = ['TOKEN', 'SECRET', 'PASSWORD', 'KEY', 'PRIVATE', 'AUTH', 'CREDENTIAL'];\n \n for (const [key, value] of Object.entries(process.env)) {\n if (value === undefined) continue;\n \n const isBlocked = blockedKeys.some(b => key.toUpperCase().includes(b));\n if (isBlocked) continue;\n \n safeEnv[key] = value;\n }\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify({\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n cwd: process.cwd(),\n env: safeEnv,\n }, null, 2),\n }],\n };\n },\n );\n\n // Expose package.json info\n server.resource(\n 'package-info',\n 'config://package',\n async (uri) => {\n try {\n const pkgPath = path.resolve(process.cwd(), 'package.json');\n const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));\n \n // Strip sensitive fields\n const { _authToken, publishConfig, ...safePkg } = pkg;\n \n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(safePkg, null, 2),\n }],\n };\n } catch {\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: 'No package.json found in current directory',\n }],\n };\n }\n },\n );\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) resource server that exposes file system, database, and configuration data as addressable resources.\n\n## Resources\n\n| URI Pattern | Description |\n|-------------|-------------|\n| \\`file:///workspace\\` | List files in working directory |\n| \\`file://{path}\\` | Read any file by path |\n| \\`db://index\\` | List all database keys |\n| \\`db://{namespace}/{key}\\` | Fetch a specific record |\n| \\`config://environment\\` | Safe environment info |\n| \\`config://package\\` | Package.json info |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\nAdd to your Claude Desktop config:\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Connecting a Real Database\n\nReplace the in-memory store in \\`src/resources/database.ts\\` with your actual data source:\n\n\\`\\`\\`typescript\n// Example with SQLite\nimport Database from 'better-sqlite3';\nconst db = new Database('./data.db');\n\n// Example with Postgres\nimport { Pool } from 'pg';\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL });\n\\`\\`\\`\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n","import type { ServerConfig, GeneratedFile } from '../types.js';\n\nexport function generatePromptServer(config: ServerConfig): GeneratedFile[] {\n const { serverName, serverDescription, packageName, author } = config;\n\n return [\n {\n path: 'src/index.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { codeReviewPrompts } from './prompts/codeReview.js';\nimport { documentationPrompts } from './prompts/documentation.js';\nimport { debuggingPrompts } from './prompts/debugging.js';\nimport { refactoringPrompts } from './prompts/refactoring.js';\n\nconst server = new McpServer({\n name: '${serverName}',\n version: '0.1.0',\n});\n\n// Register prompt collections\ncodeReviewPrompts.register(server);\ndocumentationPrompts.register(server);\ndebuggingPrompts.register(server);\nrefactoringPrompts.register(server);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('${serverName} MCP prompt server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err);\n process.exit(1);\n});\n`,\n },\n {\n path: 'src/prompts/codeReview.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Code review prompt templates.\n * Structured prompts that guide thorough, consistent code reviews.\n */\nexport const codeReviewPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'code-review',\n 'Comprehensive code review with focus areas',\n {\n code: z.string().describe('The code to review'),\n language: z.string().optional().describe('Programming language (e.g. TypeScript, Python)'),\n context: z.string().optional().describe('What does this code do? Any relevant context?'),\n focus: z.enum(['security', 'performance', 'readability', 'correctness', 'all'])\n .optional()\n .default('all')\n .describe('Area to focus the review on'),\n },\n ({ code, language, context, focus }) => {\n const lang = language ?? 'unknown';\n const focusInstructions: Record<string, string> = {\n security: \\`Focus specifically on security vulnerabilities:\n- Input validation and sanitization\n- Authentication and authorization flaws\n- Injection vulnerabilities (SQL, XSS, command)\n- Sensitive data exposure\n- Insecure dependencies\\`,\n performance: \\`Focus specifically on performance:\n- Time complexity of algorithms (Big O)\n- Unnecessary re-renders or recomputations\n- Memory leaks or excessive allocations\n- N+1 query problems\n- Missing indexes or caching opportunities\\`,\n readability: \\`Focus specifically on readability and maintainability:\n- Naming clarity (variables, functions, classes)\n- Function/method length and single responsibility\n- Comment quality (explain why, not what)\n- Consistent style and conventions\n- Dead code or confusing abstractions\\`,\n correctness: \\`Focus specifically on correctness:\n- Edge cases and boundary conditions\n- Error handling completeness\n- Race conditions or concurrency issues\n- Incorrect assumptions in logic\n- Missing null/undefined checks\\`,\n all: \\`Review all aspects: security, performance, readability, correctness, and design.\\`,\n };\n \n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Please perform a detailed code review of the following \\${lang} code.\n\n\\${context ? \\`Context: \\${context}\\\\n\\\\n\\` : ''}\\${focusInstructions[focus ?? 'all']}\n\nFor each issue found:\n1. Quote the specific code\n2. Explain the problem\n3. Provide a concrete fix\n\nRate severity as: 🔴 Critical | 🟠 High | 🟡 Medium | 🔵 Low | 💡 Suggestion\n\nCode to review:\n\\\\\\`\\\\\\`\\\\\\`\\${lang}\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'security-audit',\n 'Security-focused code audit',\n {\n code: z.string().describe('Code to audit'),\n threat_model: z.string().optional().describe('Who are the potential attackers? What are they after?'),\n },\n ({ code, threat_model }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Perform a security audit on this code.\n\n\\${threat_model ? \\`Threat model: \\${threat_model}\\\\n\\\\n\\` : ''}\nCheck for:\n- OWASP Top 10 vulnerabilities\n- Authentication/authorization bypasses\n- Data validation and sanitization\n- Cryptographic weaknesses\n- Dependency vulnerabilities\n- Secrets or credentials in code\n- Information disclosure\n\nFor each finding, provide:\n- CVE category (if applicable)\n- Severity (Critical/High/Medium/Low)\n- Attack vector\n- Remediation steps\n\nCode:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/documentation.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Documentation generation prompts.\n */\nexport const documentationPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'generate-docs',\n 'Generate comprehensive documentation for code',\n {\n code: z.string().describe('Code to document'),\n style: z.enum(['jsdoc', 'tsdoc', 'docstring', 'markdown']).optional().default('tsdoc'),\n audience: z.enum(['internal', 'public-api', 'tutorial']).optional().default('public-api'),\n },\n ({ code, style, audience }) => {\n const styleGuides: Record<string, string> = {\n jsdoc: 'Use JSDoc format with @param, @returns, @throws, @example tags',\n tsdoc: 'Use TSDoc format with @param, @returns, @throws, @example, @remarks tags',\n docstring: 'Use Python docstring format (Google style)',\n markdown: 'Generate a Markdown documentation section',\n };\n \n const audienceGuides: Record<string, string> = {\n internal: 'This is for internal developers. Focus on implementation details and gotchas.',\n 'public-api': 'This is a public API. Focus on usage, parameters, and examples. Hide implementation details.',\n tutorial: 'This is for beginners. Explain concepts, provide step-by-step examples.',\n };\n \n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Generate documentation for the following code.\n\nFormat: \\${styleGuides[style ?? 'tsdoc']}\nAudience: \\${audienceGuides[audience ?? 'public-api']}\n\nInclude:\n- Overview/description\n- Parameter documentation with types\n- Return value documentation\n- Thrown errors/exceptions\n- At least one usage example\n- Any important notes or caveats\n\nCode:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\\`,\n },\n },\n ],\n };\n },\n );\n\n server.prompt(\n 'readme-generator',\n 'Generate a README.md for a project',\n {\n project_name: z.string().describe('Project name'),\n description: z.string().describe('What does this project do?'),\n tech_stack: z.string().describe('Technologies used (e.g. Node.js, TypeScript, React)'),\n main_features: z.string().describe('Key features, one per line'),\n },\n ({ project_name, description, tech_stack, main_features }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Generate a professional README.md for this project.\n\nProject: \\${project_name}\nDescription: \\${description}\nTech Stack: \\${tech_stack}\nFeatures:\n\\${main_features}\n\nInclude these sections:\n1. Title and badges (placeholder)\n2. Description\n3. Features list\n4. Installation\n5. Quick start / usage example\n6. API reference (if applicable)\n7. Configuration\n8. Contributing\n9. License\n\nMake it clear, engaging, and developer-friendly.\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/debugging.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Debugging assistance prompts.\n */\nexport const debuggingPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'debug-error',\n 'Debug an error with full context analysis',\n {\n error_message: z.string().describe('The error message or stack trace'),\n code: z.string().optional().describe('Relevant code where the error occurs'),\n expected: z.string().optional().describe('What you expected to happen'),\n actual: z.string().optional().describe('What actually happened'),\n environment: z.string().optional().describe('Runtime environment (e.g. Node 18, Chrome 120)'),\n },\n ({ error_message, code, expected, actual, environment }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Help me debug this error.\n\nError:\n\\\\\\`\\\\\\`\\\\\\`\n\\${error_message}\n\\\\\\`\\\\\\`\\\\\\`\n\\${code ? \\`\\\\nRelevant code:\\\\n\\\\\\`\\\\\\`\\\\\\`\\\\n\\${code}\\\\n\\\\\\`\\\\\\`\\\\\\`\\` : ''}\n\\${expected ? \\`\\\\nExpected: \\${expected}\\` : ''}\n\\${actual ? \\`\\\\nActual: \\${actual}\\` : ''}\n\\${environment ? \\`\\\\nEnvironment: \\${environment}\\` : ''}\n\nPlease:\n1. Identify the root cause\n2. Explain why this error occurs\n3. Provide a step-by-step fix\n4. Suggest how to prevent this in the future\\`,\n },\n },\n ],\n }),\n );\n\n server.prompt(\n 'rubber-duck',\n 'Explain code logic to find bugs through explanation',\n {\n code: z.string().describe('Code you want to explain/debug'),\n problem: z.string().describe('What problem are you trying to solve with this code?'),\n },\n ({ code, problem }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`I'll explain my code to you and you help me find bugs through questioning.\n\nProblem I'm trying to solve: \\${problem}\n\nMy code:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nAs I explain my code, please:\n1. Ask clarifying questions about assumptions I'm making\n2. Point out any logical inconsistencies\n3. Highlight edge cases I might not be handling\n4. Don't give me the answer directly — help me discover it through questions\n\nLet's start: what questions do you have about my approach?\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'src/prompts/refactoring.ts',\n content: `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\n/**\n * Code refactoring prompts.\n */\nexport const refactoringPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'refactor',\n 'Refactor code with specific goals',\n {\n code: z.string().describe('Code to refactor'),\n goals: z.string().describe('What do you want to improve? (e.g. reduce complexity, improve testability)'),\n constraints: z.string().optional().describe('Any constraints (e.g. must keep same API, cannot use classes)'),\n language: z.string().optional().describe('Programming language'),\n },\n ({ code, goals, constraints, language }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Refactor this \\${language ?? ''} code to achieve the following goals:\n\nGoals: \\${goals}\n\\${constraints ? \\`Constraints: \\${constraints}\\` : ''}\n\nOriginal code:\n\\\\\\`\\\\\\`\\\\\\`\\${language ?? ''}\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nPlease:\n1. Explain your refactoring strategy\n2. Provide the refactored code\n3. Highlight what changed and why\n4. Note any tradeoffs\\`,\n },\n },\n ],\n }),\n );\n\n server.prompt(\n 'extract-function',\n 'Extract logic into well-named functions',\n {\n code: z.string().describe('Code containing logic to extract'),\n description: z.string().describe('Describe the logic you want to extract'),\n },\n ({ code, description }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`Help me extract the following logic into a well-named function:\n\nLogic to extract: \\${description}\n\nFrom this code:\n\\\\\\`\\\\\\`\\\\\\`\n\\${code}\n\\\\\\`\\\\\\`\\\\\\`\n\nPlease provide:\n1. The extracted function with a clear, descriptive name\n2. The modified original code calling the new function\n3. Any parameters the function needs\n4. Proper TypeScript types if applicable\\`,\n },\n },\n ],\n }),\n );\n },\n};\n`,\n },\n {\n path: 'package.json',\n content: JSON.stringify({\n name: packageName,\n version: '0.1.0',\n description: serverDescription,\n type: 'module',\n scripts: {\n build: 'tsc',\n dev: 'tsc --watch',\n start: 'node dist/index.js',\n prepublishOnly: 'npm run build',\n },\n engines: { node: '>=18.0.0' },\n dependencies: {\n '@modelcontextprotocol/sdk': '^1.0.0',\n zod: '^3.22.0',\n },\n devDependencies: {\n '@types/node': '^22.0.0',\n typescript: '^5.0.0',\n },\n }, null, 2),\n },\n {\n path: 'tsconfig.json',\n content: JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n lib: ['ES2022'],\n outDir: 'dist',\n rootDir: 'src',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n declaration: true,\n sourceMap: true,\n resolveJsonModule: true,\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'dist'],\n }, null, 2),\n },\n {\n path: '.gitignore',\n content: `node_modules/\ndist/\n*.js.map\n*.d.ts.map\n.env\n.env.local\n*.log\n.DS_Store\n`,\n },\n {\n path: 'README.md',\n content: `# ${serverName}\n\n${serverDescription}\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io) prompt server that provides structured, high-quality prompts for software development tasks.\n\n## Prompts\n\n### Code Review\n| Prompt | Description |\n|--------|-------------|\n| \\`code-review\\` | Comprehensive review with severity ratings |\n| \\`security-audit\\` | Security-focused code audit |\n\n### Documentation \n| Prompt | Description |\n|--------|-------------|\n| \\`generate-docs\\` | Generate JSDoc/TSDoc/docstrings |\n| \\`readme-generator\\` | Generate a full README.md |\n\n### Debugging\n| Prompt | Description |\n|--------|-------------|\n| \\`debug-error\\` | Debug errors with full context |\n| \\`rubber-duck\\` | Guided explanation-based debugging |\n\n### Refactoring\n| Prompt | Description |\n|--------|-------------|\n| \\`refactor\\` | Refactor with specific goals and constraints |\n| \\`extract-function\\` | Extract logic into named functions |\n\n## Setup\n\n\\`\\`\\`bash\nnpm install\nnpm run build\n\\`\\`\\`\n\n## Usage with Claude Desktop\n\n\\`\\`\\`json\n{\n \"mcpServers\": {\n \"${serverName}\": {\n \"command\": \"node\",\n \"args\": [\"${config.targetDir}/dist/index.js\"]\n }\n }\n}\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nnpm run dev # Watch mode\nnpm start # Run the server\n\\`\\`\\`\n\n## Adding Prompts\n\nCreate a new file in \\`src/prompts/\\` and register it in \\`src/index.ts\\`:\n\n\\`\\`\\`typescript\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nexport const myPrompts = {\n register(server: McpServer) {\n server.prompt(\n 'my-prompt-name',\n 'Description of what this prompt does',\n {\n input: z.string().describe('User input'),\n },\n ({ input }) => ({\n messages: [\n {\n role: 'user',\n content: { type: 'text', text: \\`Do something with: \\${input}\\` },\n },\n ],\n }),\n );\n },\n};\n\\`\\`\\`\n\n## Author\n\n${author}\n`,\n },\n ];\n}\n","import path from 'path';\nimport chalk from 'chalk';\nimport fs from 'fs-extra';\n\nexport interface AddOptions {\n force?: boolean;\n dryRun?: boolean;\n}\n\nconst TOOL_TEMPLATE = (name: string) => `import { z } from 'zod';\n\nexport const ${toCamelCase(name)}Tool = {\n name: '${toSnakeCase(name)}',\n description: 'Description of what this tool does',\n inputSchema: {\n input: z.string().describe('Primary input'),\n options: z.object({\n verbose: z.boolean().optional().default(false),\n }).optional(),\n },\n handler: async ({ input, options }: {\n input: string;\n options?: { verbose?: boolean };\n }) => {\n try {\n // TODO: Implement tool logic\n const result = \\`Processed: \\${input}\\`;\n\n if (options?.verbose) {\n console.error(\\`[${toSnakeCase(name)}] input=\\${input}\\`);\n }\n\n return {\n content: [{ type: 'text' as const, text: result }],\n };\n } catch (err: any) {\n return {\n content: [{ type: 'text' as const, text: \\`Error: \\${err.message}\\` }],\n isError: true,\n };\n }\n },\n};\n`;\n\nconst RESOURCE_TEMPLATE = (name: string) => `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\n\nconst SCHEME = '${toKebabCase(name)}://';\n\nexport const ${toCamelCase(name)}Resources = {\n register(server: McpServer) {\n // List available resources\n server.resource(\n \\`\\${SCHEME}list\\`,\n new ResourceTemplate(\\`\\${SCHEME}list\\`, { list: undefined }),\n async (uri) => {\n // TODO: Return list of available ${name} resources\n return {\n contents: [\n {\n uri: \\`\\${SCHEME}example\\`,\n mimeType: 'text/plain',\n text: 'Example ${name} resource',\n },\n ],\n };\n },\n );\n\n // Get a specific resource by ID\n server.resource(\n \\`\\${SCHEME}{id}\\`,\n new ResourceTemplate(\\`\\${SCHEME}{id}\\`, { list: undefined }),\n async (uri, { id }) => {\n // TODO: Fetch resource by id\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'text/plain',\n text: \\`Content for ${name} resource: \\${id}\\`,\n },\n ],\n };\n },\n );\n },\n};\n`;\n\nconst PROMPT_TEMPLATE = (name: string) => `import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nexport function register${toPascalCase(name)}Prompt(server: McpServer) {\n server.prompt(\n '${toKebabCase(name)}',\n {\n // Define prompt arguments\n input: z.string().describe('Primary input for the ${name} prompt'),\n context: z.string().optional().describe('Additional context'),\n focus: z.string().optional().describe('Specific focus area or constraint'),\n },\n ({ input, context, focus }) => {\n const contextSection = context ? \\`\\\\n\\\\nContext:\\\\n\\${context}\\` : '';\n const focusSection = focus ? \\`\\\\n\\\\nFocus on: \\${focus}\\` : '';\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: \\`# ${toPascalCase(name.replace(/-/g, ' '))}\n\n\\${input}\\${contextSection}\\${focusSection}\n\nPlease provide a thorough, structured response.\\`,\n },\n },\n ],\n };\n },\n );\n}\n`;\n\nfunction toCamelCase(str: string): string {\n return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());\n}\n\nfunction toPascalCase(str: string): string {\n const camel = toCamelCase(str);\n return camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[-]/g, '_').replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');\n}\n\nfunction toKebabCase(str: string): string {\n return str.replace(/[_]/g, '-').replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');\n}\n\nexport async function addCommand(\n type: string | undefined,\n name: string | undefined,\n opts: AddOptions,\n): Promise<void> {\n console.log();\n\n if (!type || !['tool', 'resource', 'prompt'].includes(type)) {\n console.log(chalk.bold('Usage:'));\n console.log(` ${chalk.cyan('create-mcp-server add tool <name>')} Add a new tool`);\n console.log(` ${chalk.cyan('create-mcp-server add resource <name>')} Add a new resource provider`);\n console.log(` ${chalk.cyan('create-mcp-server add prompt <name>')} Add a new prompt template`);\n console.log();\n console.log(chalk.dim('Examples:'));\n console.log(` ${chalk.cyan('create-mcp-server add tool github-search')}`);\n console.log(` ${chalk.cyan('create-mcp-server add resource postgres-db')}`);\n console.log(` ${chalk.cyan('create-mcp-server add prompt summarize')}`);\n console.log();\n return;\n }\n\n if (!name) {\n console.error(chalk.red(`❌ Please provide a name: create-mcp-server add ${type} <name>`));\n process.exit(1);\n }\n\n const cwd = process.cwd();\n let filePath: string;\n let content: string;\n let dir: string;\n\n switch (type) {\n case 'tool':\n dir = path.join(cwd, 'src', 'tools');\n filePath = path.join(dir, `${toCamelCase(name)}.ts`);\n content = TOOL_TEMPLATE(name);\n break;\n case 'resource':\n dir = path.join(cwd, 'src', 'resources');\n filePath = path.join(dir, `${toCamelCase(name)}.ts`);\n content = RESOURCE_TEMPLATE(name);\n break;\n case 'prompt':\n dir = path.join(cwd, 'src', 'prompts');\n filePath = path.join(dir, `${toCamelCase(name)}.ts`);\n content = PROMPT_TEMPLATE(name);\n break;\n default:\n process.exit(1);\n }\n\n const relativePath = path.relative(cwd, filePath);\n\n if (opts.dryRun) {\n console.log(chalk.bold.yellow('🔍 Dry run — would create:'));\n console.log(` ${chalk.cyan(relativePath)}`);\n console.log();\n console.log(chalk.dim('Run without --dry-run to write the file.'));\n return;\n }\n\n const exists = await fs.pathExists(filePath);\n if (exists && !opts.force) {\n console.error(chalk.yellow(`⚠️ File already exists: ${relativePath}`));\n console.error(chalk.dim(' Use --force to overwrite.'));\n process.exit(1);\n }\n\n await fs.ensureDir(dir);\n await fs.writeFile(filePath, content, 'utf8');\n\n console.log(chalk.green(`✅ Created ${relativePath}`));\n console.log();\n console.log(chalk.bold('Next:'));\n console.log(\n chalk.dim(\n ` Import and register your new ${type} in ${chalk.white('src/index.ts')}`,\n ),\n );\n\n if (type === 'tool') {\n console.log(chalk.dim(`\\n import { ${toCamelCase(name)}Tool } from './tools/${toCamelCase(name)}.js';`));\n console.log(\n chalk.dim(\n ` server.tool(${toCamelCase(name)}Tool.name, ${toCamelCase(name)}Tool.description, ${toCamelCase(name)}Tool.inputSchema, ${toCamelCase(name)}Tool.handler);`,\n ),\n );\n } else if (type === 'resource') {\n console.log(chalk.dim(`\\n import { ${toCamelCase(name)}Resources } from './resources/${toCamelCase(name)}.js';`));\n console.log(chalk.dim(` ${toCamelCase(name)}Resources.register(server);`));\n } else if (type === 'prompt') {\n console.log(\n chalk.dim(\n `\\n import { register${toPascalCase(name)}Prompt } from './prompts/${toCamelCase(name)}.js';`,\n ),\n );\n console.log(chalk.dim(` register${toPascalCase(name)}Prompt(server);`));\n }\n console.log();\n}\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQzB;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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;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,IAwHX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA2DX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA0HX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAuGX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;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;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,IAmFX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["chalk","path","chalk","fs","path","chalk","fs","path","chalk","fs","chalk"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webbywisp/create-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Scaffold production-ready MCP (Model Context Protocol) servers — tool-server, resource-server, and prompt-server templates with full TypeScript setup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"commander": "^14.0.3",
|
|
38
38
|
"fs-extra": "^11.3.4",
|
|
39
39
|
"inquirer": "^13.3.2",
|
|
40
|
-
"ora": "^9.3.0"
|
|
40
|
+
"ora": "^9.3.0",
|
|
41
|
+
"simple-git": "^3.33.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/fs-extra": "^11.0.4",
|