yamcp
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., "@yamcpserve the openapi.yaml file as a secure MCP server"
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.
yamcp
Serve any OpenAPI spec as a secure MCP server — scoped auth, per-tool allow/deny policies, rate limiting, and a redacted audit trail. One command.
npx @adamgalmor/yamcp serve --config yamcp.config.jsonThe problem
Your customers' AI agents (Claude, ChatGPT, coding assistants) want to call your API — but exposing an API to an autonomous agent is not the same as exposing it to a developer:
Every MCP server you find on GitHub skips security. No caller auth, no audit trail, no way to say "agents may read, never delete."
Enterprises block agent access outright because there is no scoped access, no logging, and no rate control between the model and the API.
Building it yourself means learning the MCP protocol, mapping your OpenAPI operations to tools by hand, and maintaining it as both evolve.
yamcp closes that gap: point it at the OpenAPI spec you already have, and it serves a policy-enforced MCP server in front of your API.
Related MCP server: Contex
How it works
Every tool call flows through a fixed pipeline — there is no way around it:
MCP client ──▶ inbound auth ──▶ allow/deny policy ──▶ rate limit ──▶ schema validation ──▶ upstream API
│
audit log (JSONL, secrets redacted) ◀──────────┘Operations → tools, automatically. Each OpenAPI operation becomes an MCP tool with a JSON Schema derived from its parameters and request body. Arguments are validated before anything touches your API.
Credentials never reach the model. Upstream API keys are referenced by environment-variable name and injected server-side. Config files contain no secrets, and
Authorizationinputs are stripped from tool schemas.Deny means invisible. Tools removed by policy or scope are not listed to the client at all — an agent cannot ask for what it cannot see.
Everything is on the record. Every call — allowed, denied, rate-limited, or failed — is one JSONL line with caller, decision, latency, and redacted arguments.
Quickstart (30 seconds)
# 1. Generate a config from your spec (lists every derived tool in an allowlist)
npx @adamgalmor/yamcp init --spec ./openapi.yaml
# 2. Trim the allowlist, set your upstream base URL, then check the result
npx @adamgalmor/yamcp list --config yamcp.config.json
# 3. Serve
export UPSTREAM_TOKEN=... # if your API needs auth
npx @adamgalmor/yamcp serve --config yamcp.config.jsonUse it from Claude Code / Claude Desktop
claude mcp add my-api -- npx @adamgalmor/yamcp serve --config /path/to/yamcp.config.jsonor in claude_desktop_config.json:
{
"mcpServers": {
"my-api": {
"command": "npx",
"args": ["@adamgalmor/yamcp", "serve", "--config", "/path/to/yamcp.config.json"],
"env": { "UPSTREAM_TOKEN": "..." }
}
}
}Configuration
{
"spec": "./openapi.yaml",
"upstream": {
"baseUrl": "https://api.example.com",
// Secrets are env-var references — never literals in this file.
"auth": { "type": "bearer", "tokenEnv": "UPSTREAM_TOKEN" },
},
"policy": {
"mode": "allowlist", // or "denylist"
"allow": ["get*", "list*"], // "*" wildcards
"deny": ["deleteUser"], // deny always wins
"readOnly": false, // true = GET/HEAD operations only
},
"rateLimit": {
"global": { "rps": 10 },
"perTool": { "createOrder": { "rps": 1, "burst": 2 } },
},
"auth": {
// Inbound auth for --http mode (stdio inherits the host process's trust).
"http": {
"tokens": [
{ "tokenEnv": "YAMCP_READ_TOKEN", "scopes": ["read"] },
{ "tokenEnv": "YAMCP_ADMIN_TOKEN", "scopes": ["read", "write"] },
],
"scopeMap": {
"read": ["get*", "list*"],
"write": ["create*", "update*"],
},
},
},
"audit": {
"destination": "./audit.jsonl", // or "stderr"
"redactFields": ["ssn", "card_number"], // merged with built-in defaults
},
}Remote mode (Streamable HTTP)
npx @adamgalmor/yamcp serve --config yamcp.config.json --http --port 3000Callers authenticate with bearer tokens; each token's scopes control which tools it can see and call. Two callers get two different tool lists.
--httprefuses to start withoutauth.httpconfigured — secure by default.Token comparison is constant-time; tokens themselves live in environment variables.
CLI
Command | What it does |
| Generate a config scaffold with every derived tool in an allowlist |
| Validate config + spec without starting a server |
| Show every tool and its effective policy decision |
| Start the MCP server (stdio by default) |
Example
A runnable petstore example lives in examples/petstore/ — the audit log below is what one session against it looks like:
{"ts":"2026-07-15T07:25:27.680Z","tool":"getPet","caller":"stdio","decision":"ok","args":{"petId":"42"},"upstreamStatus":200,"latencyMs":99}
{"ts":"2026-07-15T07:25:27.697Z","tool":"deletePet","caller":"stdio","decision":"denied"}Current limitations
Request bodies must be JSON (
application/jsonor+jsonmedia types); operations with form/multipart bodies are skipped with a warning at startup.Rate limits are in-memory and per-process — the right shape for MCP's process-per-client model, not for a fleet behind a load balancer.
Upstream auth is static bearer/API-key via env vars; OAuth flows to the upstream are on the roadmap.
Security model
See SECURITY.md for the threat model and design decisions.
Development
npm install
npm run build
npm test # 55 tests: unit + end-to-end over in-memory and HTTP transportsMIT © yamcp contributors
This server cannot be deployed
Maintenance
Related MCP Connectors
Create hosted MCP servers from any OpenAPI spec. Requires a free Kaiva Bridge account.
- typeshipOAuthdev.typeship
Generate a typed SDK, CLI, and MCP server from any OpenAPI or GraphQL spec, and keep them current.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceGenerates safe-by-default MCP servers from OpenAPI specs, exposing only low-risk GET tools and blocking write operations.5MIT
- 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 gradedqualityDmaintenanceTurns OpenAPI specs into MCP tools with secure defaults, risk inspection, confirmation gates, response limits, audit logging, and secret redaction.-
- AlicenseNot gradedqualityBmaintenanceTurns any OpenAPI/Swagger spec into an MCP server, generating one tool per endpoint with zero code.5 npmMIT