MyMCP

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: MPL-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 7 GitHub stars
Code Gecti
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

A MCP Server for any API

README.md

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.

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.

Yorumlar (0)

Sonuc bulunamadi