ogen-mcp

module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2026 License: GPL-3.0

README

ogen-mcp

ogen-mcp generates a Code Mode MCP server scaffold from an OpenAPI spec.

Instead of one MCP tool per endpoint, generated code exposes two fixed tools:

  • search with { "code": "..." } for read-only discovery against spec
  • execute with { "code": "..." } for request execution through api.request(...)

This keeps tool surface and prompt footprint stable as your API grows.

Install

go install github.com/ethpandaops/ogen-mcp/cmd/ogen-mcp@latest

Or build from source:

git clone https://github.com/ethpandaops/ogen-mcp.git
cd ogen-mcp
go build ./cmd/ogen-mcp/

Requires Go 1.26+.

Quick Start

ogen-mcp -i openapi.yaml -o mcpserver/mcp_gen.go --package mcpserver

OpenAPI 3.1 Support

ogen-mcp supports OpenAPI 3.1 specs, with one current compatibility guard:

  • Supported: normal 3.1 schemas, including nullable modeled as oneOf with { type: "null" }
  • Unsupported (fails fast): schema type arrays that include "null" (for example type: ["string", "null"])

When this unsupported pattern is detected, ogen-mcp returns a targeted error with the schema path and asks you to rewrite using oneOf.

This guard exists because upstream ogen still tracks this case separately:

Generated code includes:

  • Engine interface (RunSearch, RunExecute)
  • JSEngine implementation (Goja-based)
  • RegisterTools() for search and execute
  • RegisterResources() for schemas and examples
    • openapi://schemas
    • openapi://schemas/{name}
    • openapi://examples
    • openapi://examples/{operationId}
  • HTTPTransport — built-in net/http transport with functional options (WithHTTPClient, WithRequestHook)
  • WithEngineHook / WithTransportHook — observability decorators for audit logging, metrics, etc.
  • BuildExecuteCode / ParseExecuteResult — Go client helpers for programmatic MCP usage

Host Wiring (Go)

package main

import (
	"context"
	"net/http"

	"github.com/modelcontextprotocol/go-sdk/mcp"
	"yourmod/mcpserver"
)

func main() {
	transport := mcpserver.NewHTTPTransport("https://api.example.com",
		mcpserver.WithRequestHook(func(ctx context.Context, req *http.Request) error {
			req.Header.Set("Authorization", "Bearer "+token)
			return nil
		}),
	)

	engine, err := mcpserver.NewJSEngine(transport, nil)
	if err != nil {
		panic(err)
	}

	srv := mcp.NewServer(&mcp.Implementation{Name: "my-api", Version: "1.0.0"}, nil)
	mcpserver.RegisterTools(srv, engine)
	mcpserver.RegisterResources(srv)
}

You can also implement the APITransport interface directly for full control over request execution.

Hooks

Wrap the engine or transport with observability decorators for audit logging, metrics, or tracing:

// Log every search/execute invocation
engine = mcpserver.WithEngineHook(engine, func(
	ctx context.Context, tool, code string,
	result *mcp.CallToolResult, err error, duration time.Duration,
) {
	log.Printf("tool=%s duration=%s err=%v", tool, duration, err)
})

// Log every outgoing API request
transport = mcpserver.WithTransportHook(transport, func(
	ctx context.Context, req mcpserver.APIRequest,
	resp *mcpserver.APIResponse, err error, duration time.Duration,
) {
	log.Printf("method=%s path=%s status=%d duration=%s",
		req.Method, req.Path, resp.StatusCode, duration)
})

Client Helpers

For Go MCP clients that call the generated server programmatically, use BuildExecuteCode and ParseExecuteResult to construct and parse execute tool calls:

code := mcpserver.BuildExecuteCode("GET", "/pets",
	mcpserver.WithQuery(map[string]any{"limit": 10}),
)
// code == `return api.request({"method":"GET","path":"/pets","query":{"limit":10}});`

result, err := client.CallTool(ctx, &mcp.CallToolRequest{...}, code)
resp, err := mcpserver.ParseExecuteResult(result)
// resp.StatusCode, resp.Headers, resp.Body

Tool Model

Runtime globals:

  • spec: compact OpenAPI projection (info, operations, schema resource URIs)

Example:

const matches = spec.operations.filter(op => op.tags.includes("pets"));
return matches.map(op => ({ id: op.operationId, method: op.method, path: op.path }));
execute

Runtime globals:

  • api.request({ method, path, pathParams?, query?, headers?, body? })

Example (multiple API requests in one code block):

const orders = api.request({ method: "GET", path: "/orders", query: { limit: 3 } });
const pets = api.request({ method: "GET", path: "/pets", query: { limit: 3 } });
return { orders, pets };

Limits and Guardrails

Generated engine enforces limits for execute:

  • max requests per run
  • timeout per run
  • max response body bytes captured
  • max output bytes returned
  • max redirects per request

Configure at generation time with CLI flags, and at runtime through EngineOptions.

CLI Reference

ogen-mcp [flags]

Flags:
  -i, --input string                     path to OpenAPI spec (required)
  -o, --output string                    output file path (default: stdout)
      --package string                   Go package name (default "mcpserver")
      --engine-interface string          generated engine interface name (default "Engine")
      --search-tool string               MCP search tool name (default "search")
      --execute-tool string              MCP execute tool name (default "execute")
      --resource-uri-prefix string       URI scheme prefix for generated resources (default "openapi")
      --runtime string                   runtime to generate (currently only: js) (default "js")
      --examples string                  example mode: resources|inline|none (default "resources")
      --no-resources                     skip schema/example resource generation
      --execute-max-requests int         max API requests per execute code run (default 10)
      --execute-timeout duration         max wall time per tool code run (default 5s)
      --execute-max-response-bytes int   max bytes captured per API response body (default 262144)
      --execute-max-output-bytes int     max total execute output bytes (default 524288)
      --execute-max-redirects int        max redirects allowed per API request (default 3)
  -h, --help                             help for ogen-mcp

License

GPLv3 — see LICENSE.

Directories

Path Synopsis
cmd
ogen-mcp command
Package main provides the ogen-mcp CLI that generates MCP Code Mode boilerplate from an OpenAPI spec.
Package main provides the ogen-mcp CLI that generates MCP Code Mode boilerplate from an OpenAPI spec.
internal
codegen
Package codegen renders Go source files from a MappedAPI using embedded templates and go/format.
Package codegen renders Go source files from a MappedAPI using embedded templates and go/format.
mapper
Package mapper transforms parsed OpenAPI operations into a Code Mode representation suitable for generation.
Package mapper transforms parsed OpenAPI operations into a Code Mode representation suitable for generation.
naming
Package naming provides string conversion utilities for mapping OpenAPI operation identifiers to Go and MCP naming conventions.
Package naming provides string conversion utilities for mapping OpenAPI operation identifiers to Go and MCP naming conventions.
parser
Package parser wraps ogen to parse an OpenAPI spec and extract IR operations along with x-mcp-* extensions.
Package parser wraps ogen to parse an OpenAPI spec and extract IR operations along with x-mcp-* extensions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL