@webbywisp/create-mcp-server 0.1.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/dist/cli.js +1806 -0
- package/dist/cli.js.map +1 -0
- package/package.json +49 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +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":"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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","chalk"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webbywisp/create-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold production-ready MCP (Model Context Protocol) servers — tool-server, resource-server, and prompt-server templates with full TypeScript setup",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"scaffold",
|
|
9
|
+
"cli",
|
|
10
|
+
"ai",
|
|
11
|
+
"llm",
|
|
12
|
+
"tools",
|
|
13
|
+
"resources",
|
|
14
|
+
"prompts"
|
|
15
|
+
],
|
|
16
|
+
"author": "Wisp",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"bin": {
|
|
20
|
+
"create-mcp-server": "dist/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"main": "./dist/cli.js",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"start": "node dist/cli.js",
|
|
30
|
+
"prepublishOnly": "npm run build"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.6.2",
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
|
+
"fs-extra": "^11.3.4",
|
|
39
|
+
"inquirer": "^13.3.2",
|
|
40
|
+
"ora": "^9.3.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/fs-extra": "^11.0.4",
|
|
44
|
+
"@types/inquirer": "^9.0.9",
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"tsup": "^8.5.1",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
}
|
|
49
|
+
}
|