Library Usage

openapi-mcp is not just a CLI tool—it is also a Go module that can be imported by third-party applications to quickly add production-grade MCP server capabilities.

Installation

To use openapi-mcp as a library in your Go project, import it:

go get github.com/jedisct1/openapi-mcp/pkg/openapi2mcp

For direct access to MCP server functionality:

go get github.com/jedisct1/openapi-mcp/pkg/mcp/server

For MCP types and utilities:

go get github.com/jedisct1/openapi-mcp/pkg/mcp/mcp

Key Components

The main package to import is github.com/jedisct1/openapi-mcp/pkg/openapi2mcp, which provides several important functions and types:

Main Functions

Function Description
LoadOpenAPISpec Loads and validates an OpenAPI specification from a file
NewServer Creates a new MCP server from an OpenAPI spec
NewServerWithOps Creates a new MCP server with specific operations
RegisterOpenAPITools Registers OpenAPI operations as MCP tools on a server
ExtractOpenAPIOperations Extracts operations from an OpenAPI spec
ServeStdio Starts the server in stdio mode
ServeStreamableHTTP (default), ServeHTTP (SSE) Starts the server in HTTP mode
GetStreamableHTTPURL Gets the URL for the Streamable HTTP endpoint
GetSSEURL, GetMessageURL Gets URLs for SSE mode endpoints

Basic Usage

Here's a simple example of how to use openapi-mcp as a library to create an MCP server:

package main

import (
	"log"
	"github.com/jedisct1/openapi-mcp/pkg/openapi2mcp"
)

func main() {
	// Load the OpenAPI spec
	specPath := os.Args[1]
	doc, err := openapi2mcp.LoadOpenAPISpec(specPath)
	if err != nil {
		log.Fatalf("Failed to load OpenAPI spec: %v", err)
	}

	// Create MCP server
	srv := openapi2mcp.NewServer("myapi", doc.Info.Version, doc)

	// Determine server mode
	if httpAddr := os.Getenv("HTTP_ADDR"); httpAddr != "" {
		log.Printf("Starting HTTP server on %s", httpAddr)
		// By default, uses StreamableHTTP
		if err := openapi2mcp.ServeStreamableHTTP(srv, httpAddr, "/mcp"); err != nil {
			log.Fatalf("HTTP server failed: %v", err)
		}
	} else {
		log.Println("Starting stdio server")
		if err := openapi2mcp.ServeStdio(srv); err != nil {
			log.Fatalf("Stdio server failed: %v", err)
		}
	}
}

HTTP Mode

When using HTTP mode, openapi-mcp serves a StreamableHTTP-based MCP server by default. For developers building HTTP clients, the package provides convenient URL helper functions:

// Get the Streamable HTTP endpoint URL
streamableURL := openapi2mcp.GetStreamableHTTPURL(":8080", "/mcp")
// Returns: "http://localhost:8080/mcp"

// For SSE mode (when using --http-transport=sse), you can use:
sseURL := openapi2mcp.GetSSEURL(":8080", "/mcp")
// Returns: "http://localhost:8080/mcp/sse"

messageURL := openapi2mcp.GetMessageURL(":8080", "/mcp", sessionID)
// Returns: "http://localhost:8080/mcp/message?sessionId="

StreamableHTTP Client Connection Flow:

  1. Send POST requests to the Streamable HTTP endpoint for requests/notifications
  2. Send GET requests to the same endpoint to listen for notifications
  3. Send DELETE requests to terminate the session

Example with curl:

# Step 1: Initialize the session
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26"}}'

# The response will include a Mcp-Session-Id header

# Step 2: Send JSON-RPC requests
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Mcp-Session-Id: " \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# Step 3: Listen for notifications
curl -N http://localhost:8080/mcp \
  -H "Mcp-Session-Id: "

SSE Client Connection Flow (when using --http-transport=sse):

  1. Connect to the SSE endpoint to establish a persistent connection
  2. Receive an `endpoint` event containing the session ID
  3. Send JSON-RPC requests to the message endpoint using the session ID
  4. Receive responses and notifications via the SSE stream

Example with curl (SSE mode):

# Step 1: Connect to SSE endpoint (keep connection open)
curl -N http://localhost:8080/mcp/sse

# Output: event: endpoint
#         data: /mcp/message?sessionId=

# Step 2: Send JSON-RPC requests (in another terminal)
curl -X POST http://localhost:8080/mcp/message?sessionId= \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Advanced Usage with MCP Package

For more advanced usage, you can work with MCP types and tools directly by importing the MCP package:

package main

import (
	"context"
	"log"
	
	"github.com/jedisct1/openapi-mcp/pkg/mcp/mcp"
	"github.com/jedisct1/openapi-mcp/pkg/mcp/server"
	"github.com/jedisct1/openapi-mcp/pkg/openapi2mcp"
)

func main() {
	// Load OpenAPI spec
	doc, err := openapi2mcp.LoadOpenAPISpec("openapi.yaml")
	if err != nil {
		log.Fatal(err)
	}
	
	// Create MCP server manually
	srv := server.NewMCPServer("myapi", doc.Info.Version)
	
	// Register OpenAPI tools
	ops := openapi2mcp.ExtractOpenAPIOperations(doc)
	openapi2mcp.RegisterOpenAPITools(srv, ops, doc, nil)
	
	// Add custom tools using the MCP package directly
	customTool := mcp.NewTool("custom",
		mcp.WithDescription("A custom tool"),
		mcp.WithString("message", mcp.Description("Message to process"), mcp.Required()),
	)
	
	srv.AddTool(customTool, func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		args := req.GetArguments()
		message := args["message"].(string)
		
		return &mcp.CallToolResult{
			Content: []mcp.Content{
				mcp.TextContent{
					Type: "text",
					Text: "Processed: " + message,
				},
			},
		}, nil
	})
	
	// Serve
	if err := server.ServeStdio(srv); err != nil {
		log.Fatal(err)
	}
}

Filtering Operations

You can filter which operations from the OpenAPI spec are registered as tools by using the ToolGenOptions:

// Extract operations with filtering
ops := openapi2mcp.ExtractOpenAPIOperations(doc)

// Create server with specific operations only
srv := openapi2mcp.NewServerWithOps("myapi", doc.Info.Version, doc, ops)

// Or register with options
opts := &openapi2mcp.ToolGenOptions{
	TagFilter: []string{"admin"}, // Only include operations with "admin" tag
	DryRun:    false,
	Version:   "v1.0",
}
openapi2mcp.RegisterOpenAPITools(srv, ops, doc, opts)

Working with Operations

You can extract and manipulate operations before registering them:

// Extract all operations
ops := openapi2mcp.ExtractOpenAPIOperations(doc)

// Filter operations manually
var filteredOps []openapi2mcp.OpenAPIOperation
for _, op := range ops {
	// Only include GET operations
	if op.Method == "GET" {
		filteredOps = append(filteredOps, op)
	}
}

// Create server with filtered operations
srv := openapi2mcp.NewServerWithOps("myapi", doc.Info.Version, doc, filteredOps)

Environment Variables for Authentication

The library respects standard environment variables for authentication:

# API Key authentication
export API_KEY="your_api_key"

# Bearer token authentication  
export BEARER_TOKEN="your_bearer_token"

# Basic authentication
export BASIC_AUTH="username:password"

# Override base URL
export OPENAPI_BASE_URL="https://api.example.com"

Complete Example

Here's a more complete example showing various options:

package main

import (
	"log"
	"os"
	
	"github.com/jedisct1/openapi-mcp/pkg/mcp/server"
	"github.com/jedisct1/openapi-mcp/pkg/openapi2mcp"
)

func main() {
	// Load the OpenAPI spec
	specPath := os.Args[1]
	doc, err := openapi2mcp.LoadOpenAPISpec(specPath)
	if err != nil {
		log.Fatalf("Failed to load OpenAPI spec: %v", err)
	}

	// Create MCP server
	srv := server.NewMCPServer("myapi", doc.Info.Version)

	// Extract operations with filtering
	ops := openapi2mcp.ExtractOpenAPIOperations(doc)
	
	// Register tools with options
	opts := &openapi2mcp.ToolGenOptions{
		TagFilter: []string{"admin", "user"}, // Only these tags
		Version:   "1.0",
		DryRun:    false,
	}
	
	toolNames := openapi2mcp.RegisterOpenAPITools(srv, ops, doc, opts)
	log.Printf("Registered %d tools: %v", len(toolNames), toolNames)

	// Determine server mode
	if httpAddr := os.Getenv("HTTP_ADDR"); httpAddr != "" {
		log.Printf("Starting HTTP server on %s", httpAddr)
		if err := server.NewStreamableHTTPServer(srv).Start(httpAddr); err != nil {
			log.Fatalf("HTTP server failed: %v", err)
		}
	} else {
		log.Println("Starting stdio server")
		if err := server.ServeStdio(srv); err != nil {
			log.Fatalf("Stdio server failed: %v", err)
		}
	}
}

API Reference

For complete API documentation, see the following Go package documentation:

Next Steps

Now that you understand how to use openapi-mcp as a library, you can: