/ Directory / Playground / mcpo (MCP-to-OpenAPI)
● Community open-webui ⚡ Instant

mcpo (MCP-to-OpenAPI)

by open-webui · open-webui/mcpo

Wrap any MCP server in OpenAPI — instant /docs, request/response schemas, OAuth — so any HTTP client (or model that doesn't speak MCP) can call it.

mcpo is a tiny FastAPI shim from the Open WebUI team that turns any stdio MCP server into a standard OpenAPI HTTP service. You wrap an MCP command (mcpo -- uvx mcp-server-time) and you instantly get /openapi.json, /docs (Swagger), JSON Schema for every tool, and OAuth support. Useful when you want an MCP server reachable from non-MCP clients (curl, Postman, OpenAI function-calling, internal services) without changing the upstream server.

Why use it

Key features

Live Demo

What it looks like in practice

mcpo-openapi-mcp.replay ▶ ready
0/0

Install

Pick your client

~/Library/Application Support/Claude/claude_desktop_config.json  · Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "mcpo-openapi-mcp": {
      "command": "uvx",
      "args": [
        "mcpo",
        "--",
        "uvx",
        "mcp-server-time"
      ]
    }
  }
}

Open Claude Desktop → Settings → Developer → Edit Config. Restart after saving.

~/.cursor/mcp.json · .cursor/mcp.json
{
  "mcpServers": {
    "mcpo-openapi-mcp": {
      "command": "uvx",
      "args": [
        "mcpo",
        "--",
        "uvx",
        "mcp-server-time"
      ]
    }
  }
}

Cursor uses the same mcpServers schema as Claude Desktop. Project config wins over global.

VS Code → Cline → MCP Servers → Edit
{
  "mcpServers": {
    "mcpo-openapi-mcp": {
      "command": "uvx",
      "args": [
        "mcpo",
        "--",
        "uvx",
        "mcp-server-time"
      ]
    }
  }
}

Click the MCP Servers icon in the Cline sidebar, then "Edit Configuration".

~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "mcpo-openapi-mcp": {
      "command": "uvx",
      "args": [
        "mcpo",
        "--",
        "uvx",
        "mcp-server-time"
      ]
    }
  }
}

Same shape as Claude Desktop. Restart Windsurf to pick up changes.

~/.continue/config.json
{
  "mcpServers": [
    {
      "name": "mcpo-openapi-mcp",
      "command": "uvx",
      "args": [
        "mcpo",
        "--",
        "uvx",
        "mcp-server-time"
      ]
    }
  ]
}

Continue uses an array of server objects rather than a map.

~/.config/zed/settings.json
{
  "context_servers": {
    "mcpo-openapi-mcp": {
      "command": {
        "path": "uvx",
        "args": [
          "mcpo",
          "--",
          "uvx",
          "mcp-server-time"
        ]
      }
    }
  }
}

Add to context_servers. Zed hot-reloads on save.

claude mcp add mcpo-openapi-mcp -- uvx mcpo -- uvx mcp-server-time

One-liner. Verify with claude mcp list. Remove with claude mcp remove.

Use Cases

Real-world ways to use mcpo (MCP-to-OpenAPI)

How to call an MCP server from curl / Postman / OpenAI function-calling

👤 Backend devs whose runtime doesn't (yet) speak MCP ⏱ ~15 min intermediate

When to use: You picked a great MCP server, but your prod stack is a Python service / OpenAI Assistants API / something that wants HTTP+JSON.

Prerequisites
  • An MCP command you'd normally launch — e.g. uvx mcp-server-time or npx -y @modelcontextprotocol/server-fetch
Flow
  1. Wrap it
    Run uvx mcpo --port 8000 -- uvx mcp-server-time and confirm /docs is up.✓ Copied
    → Swagger UI shows the tools as endpoints
  2. Call from curl
    Show me a working curl that calls the time tool with timezone=America/Los_Angeles.✓ Copied
    → Returns current time + tz info
  3. Wire to OpenAI
    Generate a function-calling spec from /openapi.json that I can paste into the OpenAI API.✓ Copied
    → Spec emitted; quick test call succeeds

Outcome: An MCP server that a non-MCP backend can drive over HTTP.

Pitfalls
  • Long-running tools timeout under default uvicorn settings — Pass --timeout-keep-alive 600 to mcpo, or front it with nginx with matching timeouts

Run several MCPs behind one HTTP service

👤 Platform engineers consolidating many MCPs ⏱ ~30 min intermediate

When to use: You want one URL hosting the time, fetch, and filesystem MCPs each at their own path prefix.

Flow
  1. Compose them
    Write the mcpo config for 3 servers — time at /time, fetch at /fetch, filesystem at /fs.✓ Copied
    → config.yaml with 3 services; mcpo serves them
  2. Add OAuth
    Configure JWT auth via the issuer of my Auth0 tenant. Endpoints require a valid token.✓ Copied
    → Calls without token return 401

Outcome: A single secured HTTP entry point hosting many MCPs.

Pitfalls
  • Tools clash when 2 servers expose the same name — mcpo namespaces by prefix; tool conflicts are resolved by URL path

Use an MCP as part of an HTTP integration test suite

👤 QA / SDET teams ⏱ ~25 min advanced

When to use: You want to assert your MCP server's behavior with standard HTTP test tools.

Flow
  1. Spin up in CI
    Add a GitHub Actions job that runs mcpo wrapping our MCP, then runs Playwright/pytest against it.✓ Copied
    → Workflow file written; passes locally
  2. Schema assertions
    Snapshot /openapi.json. Fail the build if the schema changes without an explicit change in the source.✓ Copied
    → Schema diff guard in CI

Outcome: Standard HTTP testing pipeline applied to an MCP server.

Pitfalls
  • Flaky if the underlying MCP imports heavy deps at startup — Add a /healthz wait loop before tests run
Combine with: github

Combinations

Pair with other MCPs for X10 leverage

mcpo-openapi-mcp + filesystem

Persist generated /openapi.json to your repo for review

Save current /openapi.json to /api/contracts/$(date +%F).json.✓ Copied
mcpo-openapi-mcp + github

Open a PR when the OpenAPI spec changes

If the snapshot diff is non-empty, open a PR titled 'OpenAPI changed'.✓ Copied

Tools

What this MCP exposes

ToolInputsWhen to callCost
GET /docs (browser) Explore tool surface visually free
GET /openapi.json (none) Codegen / function-calling specs free
POST /<tool> JSON body matching tool input schema Invoke a wrapped MCP tool over HTTP 1 underlying MCP call

Cost & Limits

What this costs to run

API quota
Bound by the wrapped MCP's quotas
Tokens per call
Adds ~50 tokens overhead
Monetary
Free (Apache 2.0)
Tip
Wrap once per process; don't spawn a fresh subprocess per request

Security

Permissions, secrets, blast radius

Credential storage: Pass through to the wrapped MCP via env vars; mcpo itself stores nothing
Data egress: Wherever the wrapped MCP would have egressed

Troubleshooting

Common errors and fixes

404 on /tool

Tool name in URL must match exactly the MCP tool name (case sensitive)

Verify: Check /docs for the right path
Underlying MCP crashed

mcpo respawns by default but logs the error — check stderr

OAuth 401 with valid token

Check audience and issuer match your config; typical mistake is missing trailing slash

Verify: Decode the JWT at jwt.io and compare aud/iss

Alternatives

mcpo (MCP-to-OpenAPI) vs others

AlternativeWhen to use it insteadTradeoff
sparfenyuk/mcp-proxyYou only need stdio↔HTTP transport bridging, not OpenAPI surfacemcp-proxy is lower-level; mcpo gives you /docs and OAuth
Hand-write a FastAPI wrapperYou need very specific business logic alongsidemcpo gives you 90% for free

More

Resources

📖 Read the official README on GitHub

🐙 Browse open issues

🔍 Browse all 400+ MCP servers and Skills