mcpo: an MCP-to-OpenAPI proxy for Open WebUI and other OpenAPI clients
A simple, secure MCP-to-OpenAPI proxy server
At a glance
- What is it?
- mcpo wraps a stdio or HTTP MCP server in a FastAPI/uvicorn process and republishes each tool as a REST endpoint with a generated OpenAPI schema. The install path is short; the interesting decisions are around auth, multi-server config and what happens when the upstream MCP process dies.
- Who is it for?
- Adopt mcpo if you already have MCP servers speaking stdio or SSE and a client that only understands OpenAPI, such as an Open WebUI instance configured with an OpenAPI tool server. Do not adopt it if your client speaks MCP natively, because the proxy adds a process and a schema layer for nothing.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 135 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap mcpo fills between MCP servers and OpenAPI clients
MCP servers usually speak over raw stdio. The README states that this transport is "inherently insecure" and incompatible with most tools, and that it lacks standard features such as docs, auth and error handling. Whatever you think of that framing, the practical consequence is real: an application that only knows how to call OpenAPI endpoints cannot start a child process and exchange JSON-RPC frames with it.
mcpo is the adapter for that situation. It takes an MCP server command, launches it, and republishes every tool the server exposes as an HTTP route with a generated OpenAPI schema. The audience is narrow but well defined: teams running Open WebUI, or any other agent framework that consumes OpenAPI tool servers, who already have MCP servers they want to reuse. The repository is MIT licensed and written in Python, with FastAPI, uvicorn and the mcp package as dependencies.
How the proxy process works: one child process, one schema per tool
The architecture visible in the repository is a single Python process. mcpo starts the target MCP server as a subprocess (or connects to an SSE or streamable-http endpoint), lists the tools the server advertises, and mounts a proxy handler for each one. FastAPI then serves the generated OpenAPI document, which is why the interactive docs are available without any configuration.
With a config file, the mapping becomes one route per server rather than one route per tool. The README shows a config with memory, time, mcp_sse and mcp_streamable_http entries, and states that each tool is accessible under its own unique route, with the schema UI at http://localhost:8000/<tool>/docs. The disabledTools key lets you hide individual tools from a server, which matters when an MCP server exposes something you do not want an LLM to call.
The transport choice is per server. A config entry with type sse points at an SSE URL and accepts a headers object; type streamable-http points at an MCP endpoint such as http://127.0.0.1:8002/mcp. Entries without a type default to the stdio command form used by Claude Desktop configs.
Installing mcpo and exposing your first MCP tool
The README recommends uv for startup speed and zero config. The uvx form runs mcpo without a persistent install, and everything after the double dash is the MCP server command mcpo should launch.
uvx mcpo --port 8000 --api-key "top-secret" -- your_mcp_server_commandAfter startup, the proxied tool is available at http://localhost:8000, and the README points to http://localhost:8000/docs for the generated schema. If you prefer a normal Python install, the equivalent is pip install mcpo followed by the same mcpo invocation.
pip install mcpo
mcpo --port 8000 --api-key "top-secret" -- your_mcp_server_commandA concrete example from the README proxies the time server, which is a good first target because it needs no credentials.
uvx mcpo --port 8000 --api-key "top-secret" -- uvx mcp-server-time --local-timezone=America/New_YorkFor more than one server, use a config file in the Claude Desktop format and start mcpo with --config. Adding --hot-reload makes mcpo watch the file and reload servers without downtime.
{
"mcpServers": {
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"]
},
"time": {
"command": "uvx",
"args": ["mcp-server-time", "--local-timezone=America/New_York"],
"disabledTools": ["convert_time"]
}
}
}With that file in place, run mcpo --config /path/to/config.json. The memory and time tools then appear at http://localhost:8000/memory and http://localhost:8000/time, each with its own docs page. If you are deploying behind a reverse proxy, --root-path moves every route under a prefix such as /api/mcpo.
The API key is the whole security story unless you configure OAuth
mcpo's default access control is a single shared API key passed with --api-key. The README presents this as adding security through trusted web standards, and it does give you a bearer-style gate in front of tools that were previously reachable only by whoever could spawn the process. It is still one secret for every tool and every caller, with no per-tool scoping visible in the documentation.
OAuth 2.1 support exists for streamable-http servers, and it defaults to dynamic client registration, so most servers need only a server_url in the oauth block. The documented flow runs once on first connection: register a client, open a browser, capture the callback, store tokens under ~/.mcpo/tokens/ for file storage, and reuse them afterwards. The README explicitly warns against setting scope, authorization_endpoint or token_endpoint in the config, because these are discovered from the server's OAuth metadata. Note the limitation: OAuth is supported for streamable-http server types, not for stdio or SSE entries.
Where mcpo is the wrong layer: long-running tools, per-user auth and native MCP clients
mcpo is a thin proxy, and thin proxies inherit the failure modes of what they wrap. The MCP server runs as a child process, so a server that crashes takes its routes with it, and the README does not document a restart policy or health endpoint for the child. If your MCP server holds in-memory state, such as the memory server in the example config, a restart loses it.
The API key model is also a poor fit for multi-tenant deployments. There is no documented way to give different callers different tool subsets; the choice is the key or no key. Teams that need per-user authorization should terminate auth in front of mcpo or wait for a richer model.
Finally, if your client already speaks MCP, mcpo is an extra hop. You pay for a second process, an HTTP round trip and a schema translation, and you gain nothing the client could not do directly. The proxy earns its place only when the consumer is OpenAPI-only.
mcpo compared with running the MCP server directly
The real alternative is not another proxy. It is pointing your client at the MCP server over its native transport, which for most servers means stdio and for some means SSE or streamable-http. That path skips mcpo entirely and preserves MCP semantics: tool listings, prompts and any protocol features the server implements pass through untouched.
The difference in approach is where the boundary sits. Native MCP keeps the protocol end to end and pushes transport concerns into the client. mcpo moves the boundary to HTTP and OpenAPI, which buys compatibility with clients that will never implement MCP, plus generated docs and a familiar auth story. It costs you a translation layer that only knows what the MCP server advertises as tools. If a server later adds MCP features outside that surface, expect mcpo to be silent about them until the project supports them.
Maintenance, releases and what the MIT licence leaves to you
The repository is not archived, and the last push was on 2026-05-17. The most recent release listed is v0.0.20 from 2026-02-27, preceded by v0.0.19 and v0.0.18 in October 2025. That is a small version number with a modest release cadence, and the pyproject version matches v0.0.20, so the project is not signalling API stability through its numbering.
Upgrade cost is low in practice. The package installs from PyPI or runs through uvx, and the Docker image is published at ghcr.io/open-webui/mcpo:main, so a container deployment can be refreshed by pulling a new tag. The Dockerfile installs uv, Node.js 22 and npm, which means the image can run npx-based MCP servers without extra setup, at the cost of a larger image.
The MIT licence places few obligations on you: keep the copyright notice, and understand that the software ships without warranty. Nothing in the repository suggests a commercial support offering, so operational questions go to the issue tracker. If you embed mcpo in a product, the practical question is not the licence text but whether you are prepared to track upstream releases yourself.
Editorial conclusion
Adopt mcpo if you already have MCP servers speaking stdio or SSE and a client that only understands OpenAPI, such as an Open WebUI instance configured with an OpenAPI tool server. Do not adopt it if your client speaks MCP natively, because the proxy adds a process and a schema layer for nothing. Before rolling it out, verify the --api-key value you pass on the command line, confirm which routes appear at /docs after startup, and check whether your MCP server needs the OAuth block in config.json rather than a static header.
Frequently asked questions
Can Open WebUI use MCP?
Open WebUI consumes OpenAPI tool servers rather than MCP directly, and mcpo is the bridge the project provides: it exposes an MCP server as an OpenAPI-compatible HTTP server. The README links to Open WebUI documentation for integrating after the server is launched.
Is there an open-source MCP client available?
mcpo itself is not an MCP client; it is a proxy that starts or connects to an MCP server and republishes its tools over OpenAPI. The repository is MIT licensed and the source is on GitHub under open-webui/mcpo.
Why does Open WebUI say "Failed to connect to MCP server"?
The README does not document that specific error message, so the cause cannot be confirmed from the project's documentation. What it does document is that mcpo must be running and reachable, that the API key passed with --api-key must match what the client sends, and that each tool has its own route such as http://localhost:8000/memory.
Is open WebUI free?
The project documentation covers mcpo, not Open WebUI's pricing, so this cannot be answered here. The relevant fact for mcpo is that it is distributed under the MIT licence.
open webui and mcpo
mcpo is the piece that lets an Open WebUI instance reach an MCP server: it runs the MCP server command and republishes its tools as OpenAPI routes on a local port, with an API key in front. The README points to Open WebUI integration docs once the server is running.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/open-webui-mcpo)
Community notes