{"slug": "i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code", "title": "I turned a real OpenAPI into an MCP server in 5 min (without losing custom code on regen)", "summary": "A developer released MCP-Generator 2.1.5, an open-source CLI that converts OpenAPI specs into MCP servers for TypeScript, Python, and Go. The update replaces the one-endpoint-per-tool approach with tag-based grouping that collapses 200 operations into roughly 8 tools, and adds marker-based 3-way merge so custom handler code survives regeneration. The project reports validation via npm run build and 196 tests across 11 suites.", "body_md": "I built an OpenAPI to MCP server generator for TypeScript, Python and Go.\n\nThe v1 mistake: 1 endpoint = 1 tool. On a real API with 200 operations, you get a 200-tool server. Nobody can use that. That was the exact feedback I got on Reddit, and it was right.\n\nWhat I changed in 2.1.5:\n\n200 operations across 8 tags become ~8 tools. Each group routes internally by `action`.\n\nnode dist/cli/index.js generate -i api.yaml -o ./out --group-by tag\n\nnode dist/cli/index.js generate -i api.yaml -o ./out --include-tags pets --group-by tag\n\nFilter before you generate\n\nOnly generate what you will use:\n\nnode dist/cli/index.js generate -i api.yaml -o ./out --path-prefix \"/users/**\" node dist/cli/index.js generate -i api.yaml -o ./out --include-paths \"/users/**,/orders/\n\nRegen without losing custom code\n\nYour code lives between markers and survives regen with a 3-way merge:\n\n// @@mcp-gen:start:get_pets\n\nconst user = await db.users.findById(args.id);\n\nreturn { content: [{ type: \"text\", text: JSON.stringify(user) }] };\n\n// @@mcp-gen🔚get_pets\n\nnode dist/cli/index.js generate -i api.yaml -o ./out --incremental\n\nReusable logic goes in handlers.custom.* — never overwritten without --force.\n\nFase 0 P0 fixes in 2.1.5\n\nTypeScript: real query serialization (get_pets({ limit: 5 }) -> /pets?limit=5)\n\nPython: _build_query / _build_headers in --http mode, including grouped tools\n\nGo: --http wired to the real APIClient, no more not yet wired stubs\n\nRegistry is v3-only with actionable errors for removed keys and v2 specs\n\nTry it with the repo example\n\ngit clone [https://github.com/ChristopherDond/MCP-Generator.git](https://github.com/ChristopherDond/MCP-Generator.git)\n\ncd MCP-Generator\n\nnpm ci\n\nnpm run build\n\nnode dist/cli/index.js generate -i examples/petstore.yaml -l typescript -o ./my-server\n\nnode dist/cli/index.js validate -i examples/petstore.yaml\n\nOr install directly:\n\nnpm install -g @christopher_dondici/[mcp-gen@2.1.5](mailto:mcp-gen@2.1.5)\n\nRepo: [https://github.com/ChristopherDond/MCP-Generator](https://github.com/ChristopherDond/MCP-Generator)\n\nValidated with npm run build + npm test (11 suites, 196 tests).", "url": "https://wpnews.pro/news/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code", "canonical_source": "https://dev.to/christopherdond/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code-on-regen-2j2k", "published_at": "2026-09-20 19:50:35+00:00", "updated_at": "2026-09-20 20:24:40.255818+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "developer-tools", "ai-tools"], "entities": ["MCP-Generator", "Christopher Dondici", "OpenAPI", "Model Context Protocol", "TypeScript", "Python", "Go", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code", "markdown": "https://wpnews.pro/news/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code.md", "text": "https://wpnews.pro/news/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code.txt", "jsonld": "https://wpnews.pro/news/i-turned-a-real-openapi-into-an-mcp-server-in-5-min-without-losing-custom-code.jsonld"}}