Skip to main content
Glama

create-server-from-template

Generate a custom MCP server using predefined TypeScript or Python templates. Modify code, add dependencies, and tailor functionality to meet specific requirements for server implementation.

Instructions

Create a new MCP server from a template.

以下のテンプレートコードをベースに、ユーザーの要求に合わせたサーバーを実装してください。 言語に応じて適切なテンプレートを選択し、必要に応じて機能を追加・変更してください。

TypeScriptテンプレート:

import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; const server = new Server({ name: "dynamic-test-server", version: "1.0.0" }, { capabilities: { tools: {} } }); // ここでツールを実装してください server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [{ name: "echo", description: "Echo back a message", inputSchema: { type: "object", properties: { message: { type: "string" } }, required: ["message"] } }] }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "echo") { // TypeScriptの型を適切に扱うため、型アサーションを使用 const message = request.params.arguments.message as string; // または any を使う: const message: any = request.params.arguments.message; return { content: [ { type: "text", text: `Echo: ${message}` } ] }; } throw new Error("Tool not found"); }); // Server startup const transport = new StdioServerTransport(); server.connect(transport);

Pythonテンプレート:

import asyncio from mcp.server import Server from mcp.server.stdio import stdio_server app = Server("dynamic-test-server") @app.list_tools() async def list_tools(): return [ { "name": "echo", "description": "Echo back a message", "inputSchema": { "type": "object", "properties": { "message": {"type": "string"} }, "required": ["message"] } } ] @app.call_tool() async def call_tool(name, arguments): if name == "echo": return [{"type": "text", "text": f"Echo: {arguments.get('message')}"}] raise ValueError(f"Tool not found: {name}") async def main(): async with stdio_server() as streams: await app.run( streams[0], streams[1], app.create_initialization_options() ) if __name__ == "__main__": asyncio.run(main())

注意事項:

  • TypeScript実装時は、引数の型を適切に扱うために型アサーション(as string)を使用するか、 明示的に型を宣言してください(例:const value: string = request.params.arguments.someValue)。

  • 複雑な型を扱う場合は、interface や type を定義して型安全性を確保することをお勧めします。

ユーザーの要求に応じて上記のテンプレートを参考にカスタマイズしてください。その際、基本的な構造を維持しつつ、ツール名や機能を変更できます。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeNoカスタマイズしたサーバーコード。テンプレートを元に変更したコードを入力してください。省略した場合はデフォルトのテンプレートが使用されます。
dependenciesNo使用するライブラリとそのバージョン(例: { "axios": "^1.0.0" })
languageYesThe programming language for the template

Implementation Reference

  • Handler logic for the 'create-server-from-template' tool. Parses arguments, determines server code (custom or default template based on language), and calls serverManager.createServer to instantiate the MCP server with optional dependencies.
    case "create-server-from-template": { const args = request.params .arguments as unknown as CreateServerFromTemplateArgs; if (!args.language) { throw new Error("Missing required argument: language"); } // LLMから提供されたカスタムコードがあればそれを使用し、なければデフォルトのテンプレートを使用 let serverCode = args.code; // コードが提供されていない場合はデフォルトテンプレートを使用 if (!serverCode) { // 既存のテンプレート選択ロジック switch (args.language) { case "typescript": serverCode = `/* TypeScriptテンプレート */`; break; case "python": serverCode = `# Pythonテンプレート`; break; default: throw new Error( `Unsupported template language: ${args.language}` ); } } const result = await serverManager.createServer( serverCode, args.language, args.dependencies ); return { content: [ { type: "text", text: JSON.stringify({ serverId: result, message: args.code ? `Created server from custom code in ${args.language}` : `Created server from ${args.language} template`, }), }, ], }; }
  • Tool definition including name, detailed description with embedded templates for TypeScript and Python, and inputSchema defining parameters: language (required, enum), optional code, and dependencies.
    const createServerFromTemplateTool: Tool = { name: "create-server-from-template", description: `Create a new MCP server from a template. 以下のテンプレートコードをベースに、ユーザーの要求に合わせたサーバーを実装してください。 言語に応じて適切なテンプレートを選択し、必要に応じて機能を追加・変更してください。 TypeScriptテンプレート: \`\`\`typescript import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; const server = new Server({ name: "dynamic-test-server", version: "1.0.0" }, { capabilities: { tools: {} } }); // ここでツールを実装してください server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [{ name: "echo", description: "Echo back a message", inputSchema: { type: "object", properties: { message: { type: "string" } }, required: ["message"] } }] }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "echo") { // TypeScriptの型を適切に扱うため、型アサーションを使用 const message = request.params.arguments.message as string; // または any を使う: const message: any = request.params.arguments.message; return { content: [ { type: "text", text: \`Echo: \${message}\` } ] }; } throw new Error("Tool not found"); }); // Server startup const transport = new StdioServerTransport(); server.connect(transport); \`\`\` Pythonテンプレート: \`\`\`python import asyncio from mcp.server import Server from mcp.server.stdio import stdio_server app = Server("dynamic-test-server") @app.list_tools() async def list_tools(): return [ { "name": "echo", "description": "Echo back a message", "inputSchema": { "type": "object", "properties": { "message": {"type": "string"} }, "required": ["message"] } } ] @app.call_tool() async def call_tool(name, arguments): if name == "echo": return [{"type": "text", "text": f"Echo: {arguments.get('message')}"}] raise ValueError(f"Tool not found: {name}") async def main(): async with stdio_server() as streams: await app.run( streams[0], streams[1], app.create_initialization_options() ) if __name__ == "__main__": asyncio.run(main()) \`\`\` 注意事項: - TypeScript実装時は、引数の型を適切に扱うために型アサーション(as string)を使用するか、 明示的に型を宣言してください(例:const value: string = request.params.arguments.someValue)。 - 複雑な型を扱う場合は、interface や type を定義して型安全性を確保することをお勧めします。 ユーザーの要求に応じて上記のテンプレートを参考にカスタマイズしてください。その際、基本的な構造を維持しつつ、ツール名や機能を変更できます。`, inputSchema: { type: "object", properties: { language: { type: "string", enum: ["typescript", "python"], description: "The programming language for the template", }, code: { type: "string", description: "カスタマイズしたサーバーコード。テンプレートを元に変更したコードを入力してください。省略した場合はデフォルトのテンプレートが使用されます。", }, dependencies: { type: "object", description: "使用するライブラリとそのバージョン(例: { \"axios\": \"^1.0.0\" })", }, }, required: ["language"], }, };
  • index.ts:1011-1022 (registration)
    Registration of the tool in the ListToolsRequest handler, where createServerFromTemplateTool is included in the returned tools list.
    server.setRequestHandler(ListToolsRequestSchema, async () => { console.error("Received ListToolsRequest"); return { tools: [ createServerFromTemplateTool, executeToolTool, getServerToolsTool, deleteServerTool, listServersTool, ], }; });
  • Core helper method in ServerManager class that implements the actual server creation logic called by the tool handler. Handles temp dir setup, deps install (npm/pip), code compilation (TS), process spawn, and MCP client connection.
    async createServer( code: string, language: string, dependencies?: Record<string, string> ): Promise<string> { const serverId = uuidv4(); const serverDir = path.join(this.serversDir, serverId); try { // Create server directory await fs.mkdir(serverDir, { recursive: true }); await fs.chmod(serverDir, 0o777); // 権限を追加 // 依存関係がある場合はインストール(シンボリックリンクは作成しない) if (dependencies && Object.keys(dependencies).length > 0) { await this.installDependencies(serverDir, dependencies, language); } else { // 依存関係がない場合のみシンボリックリンクを作成 try { await fs.symlink( "/app/node_modules", path.join(serverDir, "node_modules") ); console.error(`Created symlink to node_modules in ${serverDir}`); } catch (error) { console.error(`Error creating symlink: ${error}`); // エラーがあっても続行する } } // Write server code to file let filePath: string; let command: string; let args: string[] = []; // 共通の環境変数設定 const appNodeModules = path.resolve("/app/node_modules"); const commonEnv = { ...process.env, PATH: process.env.PATH || "/usr/local/bin:/usr/bin:/bin", NODE_PATH: appNodeModules, }; console.error(`Current PATH: ${process.env.PATH}`); console.error(`Current NODE_PATH: ${process.env.NODE_PATH}`); switch (language) { case "typescript": filePath = path.join(serverDir, "index.ts"); const jsFilePath = path.join(serverDir, "index.js"); const tsConfigPath = path.join(__dirname, "tsconfig.json"); await fs.writeFile(filePath, code); // 絶対パスを取得して出力 command = await getCommandPath("npx"); console.error(`Using command path for npx: ${command}`); // TypeScriptをコンパイルする方法に変更 await new Promise<void>((resolve, reject) => { const tscCommand = "npx"; const tscArgs = [ "tsc", "--allowJs", filePath, "--outDir", serverDir, "--target", "ES2020", "--module", "NodeNext", "--moduleResolution", "NodeNext", "--esModuleInterop", "--skipLibCheck", "--resolveJsonModule", ]; console.error( `Compiling TypeScript: ${tscCommand} ${tscArgs.join(" ")}` ); const compileProcess = spawn(tscCommand, tscArgs, { stdio: ["ignore", "pipe", "pipe"], shell: true, env: commonEnv, cwd: "/app", // アプリケーションのルートディレクトリを指定 }); compileProcess.stdout.on("data", (data) => { console.error(`TSC stdout: ${data}`); }); compileProcess.stderr.on("data", (data) => { console.error(`TSC stderr: ${data}`); }); compileProcess.on("exit", (code) => { if (code === 0) { console.error(`TypeScript compilation successful`); resolve(); } else { console.error( `TypeScript compilation failed with code ${code}` ); reject( new Error(`TypeScript compilation failed with code ${code}`) ); } }); }); // コンパイルされたJavaScriptを実行 command = await getCommandPath("node"); args = [jsFilePath]; break; case "javascript": filePath = path.join(serverDir, "index.js"); await fs.writeFile(filePath, code); command = await getCommandPath("node"); args = [filePath]; break; case "python": filePath = path.join(serverDir, "server.py"); await fs.writeFile(filePath, code); command = await getCommandPath("python"); args = [filePath]; break; default: throw new Error(`Unsupported language: ${language}`); } console.error(`Spawning process: ${command} ${args.join(" ")}`); // サーバープロセスを起動(パイプに変更) const childProcess = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"], // inheritではなくpipeを使用 shell: true, env: commonEnv, cwd: process.cwd(), }); // 標準エラー出力のログ取得 childProcess.stderr.on("data", (data) => { console.error(`Child process stderr: ${data}`); }); // 標準出力のログ取得 childProcess.stdout.on("data", (data) => { console.error(`Child process stdout: ${data}`); }); // Create MCP client to communicate with the server const transport = new StdioClientTransport({ command, args, env: commonEnv, // 同じ環境変数を使用 }); const client = new Client( { name: "mcp-create-client", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); try { await client.connect(transport); console.error(`Connected to server ${serverId}`); } catch (error) { console.error(`Error connecting to server ${serverId}:`, error); childProcess.kill(); throw error; } // Store server info this.servers.set(serverId, { process: childProcess, client, transport, language, filePath, }); // Handle process exit childProcess.on("exit", (code) => { console.error(`Server ${serverId} exited with code ${code}`); this.servers.delete(serverId); }); return serverId; } catch (error) { // Clean up on error console.error(`Error creating server:`, error); try { await fs.rm(serverDir, { recursive: true, force: true }); } catch (cleanupError) { console.error(`Error cleaning up server directory: ${cleanupError}`); } throw error; } }
  • TypeScript interface defining the expected arguments for the create-server-from-template tool, used for type casting in the handler.
    interface CreateServerFromTemplateArgs { language: "typescript" | "python"; code?: string; dependencies?: Record<string, string>; // 例: { "axios": "^1.0.0" } }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tesla0225/mcp-create'

If you have feedback or need assistance with the MCP directory API, please join our Discord server