MyMCP
Provides tools for interacting with Asana's API, enabling management of tasks, projects, and teams.
Provides tools for interacting with Box's API, enabling file management, collaboration, and content operations.
Provides tools for interacting with DigitalOcean's API, enabling management of droplets, Kubernetes clusters, networking, and other resources.
Provides tools for interacting with OpenAI's API, enabling access to models and AI capabilities.
Provides tools for interacting with Slack's Web API, enabling messaging, channel management, and workspace operations.
Provides tools for interacting with Stripe's API, enabling payments, customers, subscriptions, and billing operations.
Provides tools for interacting with Twilio's API, enabling communication services such as SMS, voice, and messaging.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MyMCPlist all pets from the Petstore API"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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/mcpHow 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 IndexCards | 66 |
| Swagger Petstore 3.0 | 19 |
| Swagger Petstore 3.1 | 3 |
| Earth App | 391 |
| Twilio | 197 |
| Box Platform | 297 |
| DigitalOcean | 659 |
| Slack Web API | 174 |
| OpenAI | 289 |
| Asana | 249 |
| 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 |
| keep operations carrying any of these tags |
| keep these HTTP methods |
| keep operations matching these glob patterns |
| drop operations matching these glob patterns |
| cap the number of tools |
| index into the description's |
| require confirmation before calling: |
| set to |
https://mymcp.gmitch215.xyz/stripe/mcp?tags=Customers&methods=get&max=40Filters 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 |
| bearer or basic credentials, and OAuth access tokens |
| an API key sent as a named header |
| an API key sent as a query parameter |
| an API key sent as a cookie |
| 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/mcpOr 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 = 120bearer_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/mcpOr 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@mymcpThe bundled servers read their credentials from TABROOM_TOKEN, DIGITALOCEAN_TOKEN and
STRIPE_SECRET_KEY. See plugin/.mcp.json.
Endpoints
Path | Purpose |
| Streamable HTTP, the current transport |
| HTTP+SSE from protocol version 2024-11-05, deprecated |
| message channel for the SSE transport |
| 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 |
| stateless, |
| handshake era |
| handshake era |
| handshake era, assumed when no version header is sent |
| 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:
| Configuration |
| an OAuth 2.1 server inside the Worker: PKCE, Client ID Metadata Documents, KV-backed tokens, and |
| Cloudflare Access, verified against the team JWKS via |
| any OpenID Connect or RFC 8414 server, via |
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 devDeploy with bun run deploy. Everything below is optional; with none of it set, MyMCP runs as a
stateless public gateway.
Binding or variable | Effect |
| KV namespace enabling tasks, stored upstream tokens and the self-hosted auth server |
| Durable Object enabling the deprecated HTTP+SSE transport |
| key for sealing elicitation state; without it, state does not survive a restart |
| extra hosts permitted to receive credentials |
|
|
|
|
| description size cap, default 12 MB |
| upstream response cap, default 2 MB |
| upstream timeout, default 20s |
|
|
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 CodeIntegration 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 -vThe 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 --strictLayout
Path | Contents |
| schema resolution, tool generation, parameter serialization, request execution |
| method dispatch, the transports, elicitation, tasks |
| upstream credentials, resource server, identity providers |
| alias resolution, description loading, caching |
| finding a description behind a documentation page |
| 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.
This server cannot be deployed
Maintenance
Related MCP Connectors
Create hosted MCP servers from any OpenAPI spec. Requires a free Kaiva Bridge account.
Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server
MCP server for AI access to Swagger by SmartBear.
MCP Spec Compliance MCP — audits any MCP server.json against the official Model Context Protocol
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConverts any OpenAPI 3.x specification into a fully functional MCP server with OAuth 2.1 support and a purely functional architecture.4 npmMIT
- FlicenseNot gradedqualityDmaintenanceDynamically creates an MCP server from any OpenAPI schema, enabling seamless integration with tools like Prompteus and Claude.4-
- AlicenseNot gradedqualityCmaintenanceAutomatically converts OpenAPI specifications into a Model Context Protocol (MCP) server instance.221 npm16MIT
- AlicenseNot gradedqualityCmaintenanceTurn any OpenAPI / Swagger spec into an agent-ready MCP server.25 npm1MIT