oapi-codegen icon indicating copy to clipboard operation
oapi-codegen copied to clipboard

Add MCP Server Code generation

Open Asafrose opened this issue 3 months ago • 1 comments

Add MCP (Model Context Protocol) Server Code Generation

This PR adds comprehensive support for generating MCP servers from OpenAPI specifications, enabling AI agents to interact with APIs through the Model Context Protocol.

Overview

The Model Context Protocol (MCP) allows AI systems to expose tools and resources in a standardized way. This implementation generates MCP server code from OpenAPI specs, automatically converting REST API operations into MCP tools with proper JSON schemas.

Key Features

1. MCP Server Generation

  • New mcp-server: true generation option
  • Generates MCPHandlerInterface with methods for each operation
  • Generates RegisterMCPTools() function to register tools with MCP server
  • Compatible with strict-server mode via adapter pattern

2. Operation Filtering with x-mcp Extension

  • Control which operations are exposed as MCP tools using x-mcp boolean extension
  • Three filtering modes via mcp-inclusion-mode configuration:
    • include (default): Include operations by default, exclude only with x-mcp: false
    • exclude: Exclude operations by default, include only with x-mcp: true
    • explicit: Require explicit x-mcp field on all operations (errors if missing)

3. Structured Input/Output Schemas

  • Automatically generates JSON schemas for tool inputs organized by parameter type:
    • path: Path parameters
    • query: Query parameters
    • header: Header parameters
    • cookie: Cookie parameters
    • body: Request body (JSON)
  • Automatically generates output schemas from response definitions

Configuration

Basic Configuration

package: api
generate:
  mcp-server: true
  strict-server: true  # Optional: enables strict mode with adapter
  models: true

With Operation Filtering

package: api
generate:
  mcp-server: true
  strict-server: true
output-options:
  mcp-inclusion-mode: "explicit"  # or "include" or "exclude"

OpenAPI Extension

paths:
  /pets/{id}:
    get:
      operationId: GetPet
      x-mcp: true  # Include in MCP server
      # ...
    delete:
      operationId: DeletePet
      x-mcp: false  # Exclude from MCP server
      # ...

Generated Code

MCPHandlerInterface

type MCPHandlerInterface interface {
    GetPet(ctx context.Context, request *mcp.CallToolRequest) (*mcp.CallToolResult, error)
    ListPets(ctx context.Context, request *mcp.CallToolRequest) (*mcp.CallToolResult, error)
}

Tool Registration

func RegisterMCPTools(mcpServer MCPServer, si MCPHandlerInterface) error {
    // Registers each operation as an MCP tool with proper schemas
}

Strict Mode Integration

When using strict-server: true, an adapter is generated:

func NewStrictMCPHandler(ssi StrictServerInterface, middlewares []StrictMCPMiddlewareFunc) MCPHandlerInterface

Implementation Details

Files Added/Modified

  • pkg/codegen/mcp.go: Core MCP generation logic (~460 lines)

    • MCPInclusionMode enum type for type-safe filtering modes
    • filterOperationsForMCP() - Filters operations based on x-mcp extension
    • GenerateMCPServer() - Generates MCP interface and registration
    • operationToMCPTool() - Converts OpenAPI operations to MCP tools
    • buildMCPInputSchema() - Builds structured input JSON schemas
    • buildMCPOutputSchema() - Extracts output schemas from responses
  • pkg/codegen/mcp_test.go: Comprehensive test suite (~490 lines)

    • Tests for x-mcp extension parsing (5 test cases)
    • Tests for operation filtering (10 test cases covering all modes)
    • Tests for schema generation
    • All tests pass successfully
  • pkg/codegen/templates/mcp/: Go templates for code generation

    • mcp-interface.tmpl - MCPHandlerInterface generation
    • mcp-register.tmpl - Tool registration function
  • pkg/codegen/templates/strict/strict-mcp.tmpl: Strict mode adapter

  • pkg/codegen/configuration.go: Configuration updates

    • Added MCPInclusionMode field to OutputOptions
    • Added validation for inclusion mode values
  • pkg/codegen/operations.go: Strict server interface logic

    • Fixed duplicate StrictServerInterface generation when using MCP with other servers
  • examples/mcp-server/: Complete working example

    • Pet store API with MCP server
    • Demonstrates tool registration and usage
    • README with usage instructions
  • go.mod: Added MCP SDK dependency

    • github.com/modelcontextprotocol/go-sdk v1.1.0

Key Technical Decisions

  1. Quoted strings for JSON schemas: Uses quoted strings with proper escaping instead of backticks to avoid Go formatter issues with long lines

  2. Filtering before generation: Operations are filtered before generating interfaces and registration code, ensuring consistency

  3. Enum type for inclusion mode: Uses MCPInclusionMode typed enum for compile-time safety instead of string literals

  4. Strict server pattern compatibility: MCP can be used standalone or with strict-server mode via adapter

  5. No duplicate interfaces: When using MCP with other servers, StrictServerInterface is only generated once

Testing

All changes are fully tested:

  • ✅ 15 new test cases for MCP filtering functionality
  • ✅ All existing tests continue to pass
  • ✅ Tested with both standalone MCP and multi-server configurations
  • ✅ Tested all three inclusion modes (include, exclude, explicit)
go test ./pkg/codegen -run "TestGetXMCPExtension|TestFilterOperationsForMCP" -v
# All 15 tests pass

Example Usage

1. Generate MCP Server Code

oapi-codegen -config cfg.yaml api.yaml > server.gen.go

2. Implement the Interface

type Server struct{}

func (s *Server) GetPet(ctx context.Context, request *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    // Extract parameters from request
    var input struct {
        Path struct {
            ID string `json:"id"`
        } `json:"path"`
    }
    if err := json.Unmarshal(request.Params.Arguments, &input); err != nil {
        return nil, err
    }

    // Your business logic here
    pet := fetchPet(input.Path.ID)

    // Return result
    result, _ := json.Marshal(map[string]interface{}{
        "id": pet.ID,
        "name": pet.Name,
    })
    return &mcp.CallToolResult{
        Content: []interface{}{
            map[string]interface{}{
                "type": "text",
                "text": string(result),
            },
        },
    }, nil
}

3. Register Tools

mcpServer := mcp.NewServer()
handler := &Server{}
RegisterMCPTools(mcpServer, handler)

Breaking Changes

None. This is a purely additive feature that doesn't affect existing generation modes.

Migration Guide

No migration needed for existing users. To adopt MCP server generation:

  1. Add mcp-server: true to your config
  2. Add the MCP SDK dependency: go get github.com/modelcontextprotocol/go-sdk/mcp
  3. Regenerate your code
  4. Implement the MCPHandlerInterface

Documentation

  • Added comprehensive README in examples/mcp-server/ with complete working example
  • Added inline documentation in all new functions and types
  • Added detailed comments explaining the three inclusion modes

Related Links

  • MCP Specification: https://github.com/modelcontextprotocol
  • MCP Go SDK: https://github.com/modelcontextprotocol/go-sdk

Checklist

  • [x] Implementation complete
  • [x] Tests added and passing
  • [x] Example application included
  • [x] Documentation added
  • [x] No breaking changes
  • [x] Follows existing code patterns (uses templates, configuration structure, etc.)
  • [x] Type-safe enum for configuration options
  • [x] Comprehensive error messages

This PR enables oapi-codegen users to seamlessly expose their OpenAPI-defined APIs as MCP tools, making them accessible to AI agents and LLM applications with minimal effort.

Asafrose avatar Oct 30 '25 15:10 Asafrose

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedgithub.com/​modelcontextprotocol/​go-sdk@​v1.1.07210010010060
Addedgolang.org/​x/​tools@​v0.34.075100100100100
Addedgolang.org/​x/​mod@​v0.25.096100100100100

View full report

socket-security[bot] avatar Nov 01 '25 11:11 socket-security[bot]