Skip to main content
Glama

MyMCP

Turns any OpenAPI description into an MCP server. Point it at a description URL and every operation becomes a tool an AI client can call, with no server to write and nothing to deploy.

Hosted at mymcp.gmitch215.xyz. Runs on Cloudflare Workers, so you can also deploy your own.

https://mymcp.gmitch215.xyz/{server}/mcp

{server} is either a preconfigured alias or a URL-encoded link to an OpenAPI description.

# preconfigured alias
https://mymcp.gmitch215.xyz/petstore/mcp

# a hostname, which is checked for a description
https://mymcp.gmitch215.xyz/api.tabroom.com/mcp

# a full description URL, percent-encoded
https://mymcp.gmitch215.xyz/https%3A%2F%2Fapi.example.com%2Fopenapi.json/mcp

How It Works

MyMCP fetches the description, resolves its schemas, and builds one MCP tool per operation. Path, query, header and cookie parameters keep the names the API gives them; a binding table records where each one belongs on the wire, so nothing has to be inferred from an argument name at call time.

When the URL does not serve a description directly, MyMCP looks for one. It reads Link: rel="service-desc" headers, then the configuration embedded by Scalar, Swagger UI, Redoc, Stoplight Elements and RapiDoc, then a list of well-known paths. Pointing at api.tabroom.com finds the description at /v1 without being told where it is.

OpenAPI 3.0, 3.1 and Swagger 2.0 are supported, in JSON or YAML.

Related MCP server: OpenAPI MCP Server

Preconfigured Servers

Alias

API

Tools

tabroom

Tabroom IndexCards

66

petstore

Swagger Petstore 3.0

19

petstore31

Swagger Petstore 3.1

3

earth-app

Earth App

391

twilio

Twilio

197

box

Box Platform

297

digitalocean

DigitalOcean

659

slack

Slack Web API

174

openai

OpenAI

289

asana

Asana

249

stripe

Stripe

594

Add more in src/servers.json. bun run servers:check validates every entry, and runs weekly in CI.

Filters

Large APIs produce hundreds of tools, which most clients handle poorly. Narrow the set with query parameters on the connection URL:

Parameter

Effect

tags

keep operations carrying any of these tags

methods

keep these HTTP methods

include

keep operations matching these glob patterns

exclude

drop operations matching these glob patterns

max

cap the number of tools

server

index into the description's servers list

confirm

require confirmation before calling: write, destructive, all, or a method list

outputSchema

set to 0 to omit generated output schemas

https://mymcp.gmitch215.xyz/stripe/mcp?tags=Customers&methods=get&max=40

Filters are part of the cache key, so two differently filtered connections do not share a tool list.

Authentication

Credentials for the upstream API travel in their own headers, never in Authorization:

Header

Use

X-Mcp-Upstream-Authorization

bearer or basic credentials, and OAuth access tokens

X-Mcp-Upstream-<Header>

an API key sent as a named header

X-Mcp-Upstream-Query-<name>

an API key sent as a query parameter

X-Mcp-Upstream-Cookie-<name>

an API key sent as a cookie

X-Mcp-Upstream-Scheme-<scheme>

a credential targeted at one named security scheme

MyMCP reads the description's securitySchemes and applies the credential where each operation expects it, covering http bearer, http basic, and apiKey in a header, query string or cookie. Any X-Mcp-Upstream-<Header> value that matches no scheme is forwarded as-is, which covers APIs that need headers their own description does not declare.

Credentials go only to hosts the description declares in its servers list, plus anything in ALLOWED_HOSTS. They are dropped on any redirect that leaves those hosts. A description fetched from an arbitrary URL therefore cannot route a credential somewhere of its own choosing.

The MCP specification forbids an MCP server from reusing the client's own credentials against a third-party API. Keeping upstream credentials in a separate header family means the caller is handing MyMCP a key for a named API rather than having an MCP token forwarded on their behalf, and leaves Authorization free for MCP's own authorization. For the flow the specification prefers, where MyMCP holds the upstream tokens itself, see Authorization.

Client Setup

Claude Code

claude mcp add --transport http petstore https://mymcp.gmitch215.xyz/petstore/mcp

# with a credential for the upstream API
claude mcp add --transport http tabroom https://mymcp.gmitch215.xyz/tabroom/mcp \
  --header "X-Mcp-Upstream-Authorization: Bearer $TABROOM_TOKEN"

Or in .mcp.json, which supports ${VAR} expansion:

{
	"mcpServers": {
		"stripe": {
			"type": "http",
			"url": "https://mymcp.gmitch215.xyz/stripe/mcp?tags=Customers",
			"headers": {
				"X-Mcp-Upstream-Authorization": "Bearer ${STRIPE_SECRET_KEY}"
			}
		}
	}
}

Use --scope project to commit the entry for a team, or --scope user to make it global. For credentials that rotate, headersHelper runs a script that prints headers as JSON.

Codex CLI

codex mcp add petstore --url https://mymcp.gmitch215.xyz/petstore/mcp

Or in ~/.codex/config.toml:

[mcp_servers.stripe]
url = "https://mymcp.gmitch215.xyz/stripe/mcp?tags=Customers"
bearer_token_env_var = "MYMCP_TOKEN"
http_headers = { "X-Mcp-Upstream-Authorization" = "Bearer sk_test_..." }
startup_timeout_sec = 20
tool_timeout_sec = 120

bearer_token_env_var sets Authorization, which MyMCP uses for its own authorization. Upstream credentials belong in http_headers.

Gemini CLI

gemini mcp add --transport http petstore https://mymcp.gmitch215.xyz/petstore/mcp

Or in ~/.gemini/settings.json:

{
	"mcpServers": {
		"petstore": {
			"httpUrl": "https://mymcp.gmitch215.xyz/petstore/mcp",
			"headers": {
				"X-Mcp-Upstream-Authorization": "Bearer ${API_TOKEN}"
			}
		}
	}
}

Gemini CLI uses httpUrl for Streamable HTTP and url for the older SSE transport.

Cursor, VS Code and Claude Desktop

All three take the same shape in their MCP configuration file:

{
	"mcpServers": {
		"petstore": {
			"type": "http",
			"url": "https://mymcp.gmitch215.xyz/petstore/mcp",
			"headers": {
				"X-Mcp-Upstream-Authorization": "Bearer ..."
			}
		}
	}
}

Claude Code Plugin

The repository is a plugin marketplace, which installs a set of servers in one step:

/plugin marketplace add gmitch215/MyMCP
/plugin install mymcp@mymcp

The bundled servers read their credentials from TABROOM_TOKEN, DIGITALOCEAN_TOKEN and STRIPE_SECRET_KEY. See plugin/.mcp.json.

Endpoints

Path

Purpose

POST /{server}/mcp

Streamable HTTP, the current transport

GET /{server}/sse

HTTP+SSE from protocol version 2024-11-05, deprecated

POST /{server}/messages

message channel for the SSE transport

GET /.well-known/oauth-protected-resource

resource metadata, when authorization is enabled

POST /{server}/sse is treated as Streamable HTTP so existing configurations keep working.

The SSE transport needs the two halves of a session to share state, which a stateless Worker cannot do alone. Bind the MCP_SSE Durable Object to enable it; without that binding, GET /{server}/sse returns 405 and points at /{server}/mcp.

Protocol Support

Version

Notes

2026-07-28

stateless, server/discover, per-request _meta, required request headers

2025-11-25

handshake era

2025-06-18

handshake era

2025-03-26

handshake era, assumed when no version header is sent

2024-11-05

HTTP+SSE transport

Methods: server/discover, initialize, ping, tools/list, tools/call, prompts/list, prompts/get, resources/list, resources/read, resources/templates/list, completion/complete, subscriptions/listen, and tasks/get, tasks/update, tasks/cancel.

On 2026-07-28, MCP-Protocol-Version, Mcp-Method and Mcp-Name are required and validated against the request body; a mismatch returns 400 with error -32020. Set MCP_STRICT_HEADERS=0 to accept requests that omit them.

Elicitation

When a client supports elicitation, MyMCP asks instead of failing:

  • A call missing required arguments returns a form requesting them.

  • With ?confirm=write, a write operation asks for confirmation before it runs.

  • When an operation needs credentials and none were supplied, a URL-mode elicitation starts the upstream sign-in flow.

The state carried between rounds is AEAD-sealed and bound to the caller, the originating request and a short expiry, so it cannot be replayed onto another call.

Tasks

With KV bound, MyMCP implements the io.modelcontextprotocol/tasks extension. An upstream that answers 202 Accepted with a Location header becomes a task; the client polls tasks/get, and MyMCP advances the upstream job on each read. Without KV the extension is not advertised, because a task handle has to outlive the request that created it.

Authorization

MyMCP is open by default. Setting AUTH_PROVIDER turns it into an OAuth 2.1 resource server: it serves RFC 9728 resource metadata, answers unauthenticated requests with 401 and a WWW-Authenticate challenge, and validates that a token's audience is this server.

Three identity providers are supported:

AUTH_PROVIDER

Configuration

selfhosted

an OAuth 2.1 server inside the Worker: PKCE, Client ID Metadata Documents, KV-backed tokens, and SELFHOST_PASSWORD for the operator

access

Cloudflare Access, verified against the team JWKS via ACCESS_TEAM_DOMAIN and ACCESS_AUD

oidc

any OpenID Connect or RFC 8414 server, via AUTH_ISSUER

With a provider and KV configured, /connect starts an OAuth flow against the upstream API using the oauth2 scheme its description declares. MyMCP stores the resulting token against the verified user and uses it on their behalf, so upstream credentials never reach the MCP client. The callback checks that the browser user is the same principal that began the flow.

Self-Hosting

git clone https://github.com/gmitch215/MyMCP.git
cd MyMCP
bun install
bun run dev

Deploy with bun run deploy. Everything below is optional; with none of it set, MyMCP runs as a stateless public gateway.

Binding or variable

Effect

MYMCP_KV

KV namespace enabling tasks, stored upstream tokens and the self-hosted auth server

MCP_SSE

Durable Object enabling the deprecated HTTP+SSE transport

STATE_SECRET

key for sealing elicitation state; without it, state does not survive a restart

ALLOWED_HOSTS

extra hosts permitted to receive credentials

ALLOWLIST_ONLY

1 to serve only the aliases in servers.json

INSECURE_UPSTREAM_HOSTS

host:port entries exempt from the network policy

MAX_SPEC_BYTES

description size cap, default 12 MB

MAX_RESPONSE_BYTES

upstream response cap, default 2 MB

FETCH_TIMEOUT_MS

upstream timeout, default 20s

MCP_STRICT_HEADERS

0 to stop requiring Mcp-Method and Mcp-Name

Network Policy

MyMCP fetches URLs a caller supplies, so it refuses anything that is not publicly routable: plain HTTP, loopback, RFC1918, carrier-grade NAT, link-local including 169.254.169.254, multicast, and the IPv6 equivalents including IPv4-mapped forms. The check runs on the description URL, every discovery candidate and each redirect hop.

INSECURE_UPSTREAM_HOSTS exempts specific host:port entries, for an instance deployed alongside a private API. Every entry is a host callers can then reach through the service.

Descriptions and their derived tool tables are cached, and concurrent requests for the same uncached description share one build.

Prompt Injection

Tool names and descriptions come from a third-party document and reach model context verbatim. MyMCP strips control characters, ANSI escapes and zero-width and bidi overrides from that text, caps its length, and states in the server instructions that the descriptions are data rather than instructions.

Development

bun run typecheck
bun run test                # unit tests, hermetic
bun run test:coverage
bun run servers:check       # validate every alias in servers.json
bun run evals               # tool-selection evals via local Claude Code

Integration tests run against real containers:

docker compose -f docker/compose.yml up -d --wait
bun run test:e2e
docker compose -f docker/compose.yml down -v

The fixtures are an echo server that reflects the request it receives, which makes the generated HTTP request directly assertable, and a static server holding the descriptions under docker/specs.

Conformance is checked with the official MCP Inspector against a running worker:

bun run dev
bunx @modelcontextprotocol/inspector@2 --cli \
  --transport http --server-url http://127.0.0.1:8787/petstore/mcp \
  --method tools/list --strict

Layout

Path

Contents

src/openapi/

schema resolution, tool generation, parameter serialization, request execution

src/mcp/

method dispatch, the transports, elicitation, tasks

src/auth/

upstream credentials, resource server, identity providers

src/resolve.ts

alias resolution, description loading, caching

src/discover.ts

finding a description behind a documentation page

src/net.ts

network policy and capped fetching

Out of Scope

Sampling, roots and logging are deprecated in the current specification with removal scheduled, so MyMCP does not implement them.

License

Mozilla Public License 2.0. See LICENSE.

Related MCP Connectors

Related MCP Servers