Skip to content

Getting started

The image ghcr.io/therealm-tech/oas2mcp is published for amd64 and arm64, tagged with each release version and latest. Its entrypoint is the oas2mcp binary, so every example below runs the same way with docker run in front.

Over stdio — keep -i, the MCP client talks to the container’s stdin:

Terminal window
docker run --rm -i ghcr.io/therealm-tech/oas2mcp \
--openapi-url https://petstore3.swagger.io/api/v3/openapi.json

Over Streamable HTTP — the image already binds 0.0.0.0:8000:

Terminal window
docker run --rm -p 8000:8000 ghcr.io/therealm-tech/oas2mcp \
http --openapi-url https://petstore3.swagger.io/api/v3/openapi.json

A local document is mounted into the container:

Terminal window
docker run --rm -i -v "$PWD/examples:/examples:ro" ghcr.io/therealm-tech/oas2mcp \
--openapi-file /examples/petstore.yaml

Requires rustup: the toolchain version is pinned in rust-toolchain.toml and installed on the first cargo invocation.

Terminal window
git clone https://github.com/therealm-tech/oas2mcp.git
cd oas2mcp
cargo build --release
# binary at target/release/oas2mcp

To run it on a cluster, see Deploying on Kubernetes.

oas2mcp [OPTIONS] [stdio | sse | http] [TRANSPORT OPTIONS]
oas2mcp healthcheck [--bind-addr ADDR]

The subcommand picks the transport, stdio when none is given. Options for one transport only exist under its subcommand: --bind-addr under sse and http, and --allowed-host, --stream-responses, --forward-header and every --inbound-* flag under http alone. Every other option may come before or after the subcommand.

healthcheck serves nothing: it exits 0 when something accepts TCP connections on --bind-addr (a wildcard address is probed on loopback), 1 otherwise. It is the container image’s HEALTHCHECK.

The OpenAPI source is required to serve: pass exactly one of --openapi-file or --openapi-url. Every option is listed in the configuration reference.

Expose the bundled Petstore example over stdio:

Terminal window
oas2mcp --openapi-file examples/petstore.yaml

The same API restated in OpenAPI 3.1 — union types, const, prefixItems, components.pathItems, a webhooks section — is in examples/petstore-3.1.yaml, and needs no different invocation:

Terminal window
oas2mcp --openapi-file examples/petstore-3.1.yaml

Serve a remote API over Streamable HTTP, forwarding a bearer token upstream:

Terminal window
oas2mcp http \
--openapi-url https://api.example.com/openapi.json \
--bind-addr 0.0.0.0:8000 \
--header 'Authorization: Bearer <token>'
# MCP endpoint: POST http://0.0.0.0:8000/mcp

Serve over the legacy SSE transport:

8000/sse
oas2mcp sse --openapi-file examples/petstore.yaml
# Client posts: POST http://127.0.0.1:8000/messages?sessionId=<id>

For a stdio client (e.g. Claude Desktop / Claude Code), point it at the binary:

{
"mcpServers": {
"petstore": {
"command": "oas2mcp",
"args": ["--openapi-file", "/abs/path/to/examples/petstore.yaml"]
}
}
}

For a remote client, start the http transport and connect it to http://<host>:<port>/mcp.