loading…
Search for a command to run...
loading…
Turn any OpenAPI specification into a smaller, LLM-friendly MCP server. Enables interaction with REST APIs through MCP tools using profiles to reduce complexity
Turn any OpenAPI specification into a smaller, LLM-friendly MCP server. Enables interaction with REST APIs through MCP tools using profiles to reduce complexity.
CI codecov npm Docker Hub License: MIT
Turn any OpenAPI specification into a smaller, LLM-friendly MCP server.
stdio or HTTP| Step | What happens | Why it matters |
|---|---|---|
| 1. Load API | mcp4openapi reads your OpenAPI spec |
Raw REST operations become available for tool generation |
| 2. Shape tools | A profile can group, filter, and simplify operations | The LLM sees fewer, more useful tools |
| 3. Connect client | Your MCP client connects over stdio or HTTP |
You use the API through MCP without custom server code |
Typical outcomes:
Start with an existing profile in profiles/, then adapt only what you need.
resources/list, resources/templates/list, resources/read, and template-variable completion from profilesHttpClient handles multipart/form-data127.0.0.1/::1), the HTTP transport enforces Host header validation and returns 403 { "error": "Forbidden" } on mismatch. This mitigates browser-based DNS rebinding attacks against local development servers.Check example profiles in profiles/.
Profiles declare a single upstream_mcp object for a remote MCP provider, or resolve it from an env-backed JSON object via upstream_mcp_from_env.
transport.type: "http-streamable"bearer, query, custom-headervalue_from_env; inline credentials are rejectedupstream_mcp_from_env is set and resolves to non-empty JSON, it overrides the static upstream_mcp objectstdio upstream providers are intentionally deferred to a later, explicitly gated iterationExample:
{
"upstream_mcp_from_env": "MCP4_UPSTREAM_MCP_JSON",
"upstream_mcp": {
"name": "remote-mcp",
"transport": {
"type": "http-streamable",
"url": "https://remote-mcp.example/mcp"
},
"auth": {
"type": "bearer",
"value_from_env": "REMOTE_MCP_TOKEN"
},
"tool_prefix": "remote",
"tools": {
"allow": ["github_*"],
"deny": ["admin_*"]
},
"timeout_ms": 30000
}
}
Use the env-backed path when deployment-specific upstreams differ between environments and you do not want to edit the checked-in profile file.
Profiles can now declare top-level resources[] for MCP Apps UIs and read-only data surfaces:
uri and preloaded file_path or bounded inline_texturi_template, optional variable completion, and optional fetch-backed rendering through declared read-only OpenAPI/composite bindingsapps metadata to attach output templates and widget metadata without changing the core tool schema generatorSee docs/PROFILE-GUIDE.md for the profile shape and validation rules.
For most users, the simplest path is:
gitlab, codecov, or n8n.mcp4openapi with npx.Minimal local example:
export MCP4_API_TOKEN=your_token
npx mcp4openapi --profile gitlab --api-base-url https://gitlab.example.com/api/v4
If you already know your MCP client, go straight to its config example. If not, use the file-location section first.
Cursor:
.cursor/mcp.json in your project root~/.config/Cursor/User/mcp.json; use ⚙ → Tools & MCP → New MCP Server)VS Code + Copilot:
.vscode/mcp.json in your project root~/.config/Code/User/mcp.json in your home directory (platform-dependent; use Ctrl+Shift+P → MCP: Open User Configuration)JetBrains IDEs + Copilot:
.idea/mcp.json in your project root~/.config/github-copilot/intellij/mcp.json (platform-dependent; use GitHub Copilot icon bottom right → Edit Setting... → Model Context Protocol (MCP) → Configure)Claude Code:
.claude/mcp.json in your project root~/.claude.json in your home directory (platform-dependent)No installation required.
Use VS Code dialog to enter access token (recommended for security):
Access Token (Bearer) example:
{
"servers": {
"mcp4openapi": {
"command": "npx",
"args": [
"-y", "mcp4openapi",
"--profile", "<profile-name>",
"--api-base-url", "https://api.example.com"
],
"env": {
"MCP4_API_TOKEN": "${input:api-token}",
}
},
"inputs": [
{
"type": "promptString",
"id": "api-token",
"description": "API Authorization Token",
"password": true
}
]
}
}
inputs section prompts you for the token when the server starts, so environment variables are not needed.
Cursor stdio example (non-OAuth, token-based auth only):
{
"mcpServers": {
"mcp4openapi": {
"command": "npx",
"args": [
"-y", "mcp4openapi",
"--profile", "<profile-name>",
"--api-base-url", "https://api.example.com"
],
"env": {
"MCP4_API_TOKEN": "${env:MCP4_API_TOKEN}",
}
}
}
}
Cursor OAuth example (HTTP transport, URL-based MCP server):
{
"mcpServers": {
"mcp4openapi-oauth": {
"url": "http://127.0.0.1:3003/profile/<profile-name>/mcp"
}
}
}
If profile defines profile_id (or profile_name or profile_alias), you can start with:
npx mcp4openapi --profile (profile-id/name/alias)
List available profiles with:
npx mcp4openapi --list-profiles
npx mcp4openapi -l
Show standard CLI info with:
npx mcp4openapi --help
npx mcp4openapi -h
npx mcp4openapi --version
npx mcp4openapi -v
Predefined profiles in the profiles/ directory contains names for easy reference:
gitlabyoutrackcodecovgithub-securitysemgrepgrafanan8nn8n-nodesProfiles are resolved from ./profiles path by default. If that directory is missing, the bundled npm package profiles are used. Override with --profiles-dir or MCP4_PROFILES_DIR.
MCP4_API_TOKEN (or equivalent environment variable name defined in your profile) with access token (Bearer) must be set for stdio transport with authenticated APIs. OAuth authorization flow is supported for HTTP transport only.claude mcp add --transport stdio mcp4openapi \
-- npx mcp4openapi --profile <profile-name> --api-base-url https://api.example.com
MCP4_API_TOKEN with access token (Bearer) must be set.{
"servers": {
"mcp4openapi": {
"command": "npx",
"args": [
"mcp4openapi",
"--profile",
"<profile-name>",
"--api-base-url",
"https://api.example.com"
],
"env": {
"MCP4_API_TOKEN": "${input:api-token}",
}
}
}
}
${input:api-token} to indicate that you need to enter the token manually in the IDE dialog.See docs/DOCKER.md for build, run, authentication modes, production deployment, and security.
1. Clone & Install:
git clone https://github.com/davidruzicka/mcp4openapi.git
cd mcp4openapi
npm install
2. Build:
npm run build
3. Configure:
cp env.example .env
# Edit .env with your settings
4. Run:
# uses .env for configuration
npm start
export MCP4_API_TOKEN=glpat-xxxxxxxxxxxx
npm start --profile mcp-profile
See docs/HTTP-TRANSPORT.md for transport options (stdio vs HTTP) and authentication modes.
Node.js has a fixed list of certificate authorities. If your MCP server uses self-signed certificates, you need to configure Node.js to trust them.
Option 1: Disable certificate validation (test only)
export NODE_TLS_REJECT_UNAUTHORIZED=0
# Persist for current user
echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> $HOME/.profile
Option 2: Add custom CA to Node.js
export NODE_EXTRA_CA_CERTS=$HOME/ca-bundle.pem
# Persist for current user
echo 'export NODE_EXTRA_CA_CERTS="$HOME/ca-bundle.pem"' >> $HOME/.profile
Option 1: Disable certificate validation (test only)
# Session only
$env:NODE_TLS_REJECT_UNAUTHORIZED = "0"
# Persist for current user
setx NODE_TLS_REJECT_UNAUTHORIZED 0
Option 2: Add custom CA to Node.js
# Session only
$env:NODE_EXTRA_CA_CERTS = "$env:USERPROFILE\ca-bundle.pem"
# Persist for current user
setx NODE_EXTRA_CA_CERTS "%USERPROFILE%\ca-bundle.pem"
Option 1: Disable certificate validation (test only)
# Session only
export NODE_TLS_REJECT_UNAUTHORIZED=0
# Persist for current user (zsh)
echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> $HOME/.zshrc
# or for bash
echo 'export NODE_TLS_REJECT_UNAUTHORIZED=0' >> $HOME/.bash_profile
Option 2: Add custom CA to Node.js
# Session only
export NODE_EXTRA_CA_CERTS="$HOME/ca-bundle.pem"
# Persist for current user (zsh)
echo 'export NODE_EXTRA_CA_CERTS="$HOME/ca-bundle.pem"' >> $HOME/.zshrc
# or for bash
echo 'export NODE_EXTRA_CA_CERTS="$HOME/ca-bundle.pem"' >> $HOME/.bash_profile
MCP4_API_TOKEN: API token (default env var name; customizable via MCP4_AUTH_ENV_VAR or profile value_from_env for auth parameters)security schemes if presentMCP4_PROFILE: Profile ID for resolving profiles from a directory (used by --profile)MCP4_PROFILES_DIR: Profiles root directory for profile ID resolution (default: ./profiles)MCP4_PROFILE_PATH: Profile JSON path (default: auto-generate tools from OpenAPI spec; warning logged if tool exceeds 60 parameters)MCP4_OPENAPI_SPEC_PATH: Path or URL to OpenAPI spec (YAML/JSON, supports local files and HTTP/HTTPS URLs). Required when profile does not provide openapi_spec_path. In HTTP profile routing, this acts as a global fallback for profiles without openapi_spec_path.MCP4_TRANSPORT: stdio (default) or httpMCP4_API_BASE_URL: Override OpenAPI server URLMCP4_TRUST_BOOTSTRAP_URLS: Set to true to skip SSRF checks for bootstrap URL fetches (remote OpenAPI spec loading and OAuth metadata discovery). Default is secure mode (false).MCP4_SSRF_ALLOW_PRIVATE_NETWORK: Set to true to allow private/loopback/link-local targets in SSRF validation paths, including bootstrap URL checks.Profile auth env vars: Use profile-specific names for value_from_env (for example, GITLAB_TOKEN, YOUTRACK_TOKEN) instead of the generic MCP4_API_TOKEN.
Enterprise authorization env vars: enterprise_authorization also supports selective *_from_env references for issuer, audience, mode, scopes, tool categories, and claim mappings so HTTP enterprise auth can be deployed without editing the profile file. See docs/OAUTH.md for the supported fields and formats.
CLI mapping rule: Documented MCP4_* env vars can be passed as a CLI flag by dropping the MCP4_ prefix and using kebab-case. Example: MCP4_PROFILE_PATH -> --profile-path, MCP4_OPENAPI_SPEC_PATH -> --openapi-spec-path. Unknown flags cause startup to fail.
Global tool filtering removes tools during profile load for every session.
MCP4_TOOL_FILTER_ALLOW_NAMES: Comma-separated tool names to keep (exact match, case-sensitive)MCP4_TOOL_FILTER_ALLOW_NAME_REGEX: Comma-separated regex patterns to allow (auto-anchored unless already wrapped with ^ and $)MCP4_TOOL_FILTER_DENY_NAMES: Comma-separated tool names to excludeMCP4_TOOL_FILTER_DENY_NAME_REGEX: Comma-separated regex patterns to exclude (auto-anchored)MCP4_TOOL_FILTER_ALLOW_CATEGORIES: Comma-separated operation categories to allow (list and/or read). Composite tools are allowed only if all steps are within the allowed categories.MCP4_TOOL_FILTER_WARN_THRESHOLD_PCT: Warn when filtered percentage exceeds this threshold (default: 90)MCP4_TOOL_FILTER_SESSION_MAX_TOOLS: Max entries in X-Mcp4-Tools header (default: 100)Regex patterns are validated for length, nested quantifiers, and alternations with quantifiers to reduce ReDoS risk.
Global parameter filtering constrains tool-call arguments process-wide in both stdio and http.
MCP4_PARAM_FILTER: Baseline parameter filter using the same format as X-Mcp4-ParamsCLI mapping:
MCP4_PARAM_FILTER -> --param-filterRules:
stdio, MCP4_PARAM_FILTER applies for the lifetime of the local process.http, MCP4_PARAM_FILTER is the baseline for every session.X-Mcp4-Params during HTTP initialization, the session header may only narrow the global baseline.Example:
npx mcp4openapi \
--transport stdio \
--tool-filter-allow-names manage_merge_requests \
--param-filter "project_id=123,_allow_read"
When running without a profile (OpenAPI spec only), authentication is automatically configured from OpenAPI spec's security schemes:
MCP4_AUTH_ENV_VAR: Environment variable name for auth token (default: MCP4_API_TOKEN)Supported OpenAPI Security Types:
http with scheme: bearer): Uses Authorization: Bearer <token> headerapiKey with in: header): Uses custom header (e.g., X-API-Key: <token>)apiKey with in: query): Adds token to query string (e.g., ?api_key=<token>)security definedExample: Use custom env var for GitLab own instance token:
export MCP4_API_TOKEN=xxxxxxxxxxxx
npm start \
--api-base-url https://gitlab.example.com/api/v4 \
--openapi-spec-path https://gitlab.example.com/api/v4/openapi.yaml
⚠️ Warning: Running without a profile may generate many tools with many parameters, leading to LLM context pollution.
For APIs with incomplete OpenAPI specs (missing security definition but requiring authentication):
MCP4_AUTH_FORCE: Enable force auth override (true|false, default: false)MCP4_AUTH_TYPE: Authentication type: bearer|query|custom-header (default: bearer)MCP4_AUTH_HEADER_NAME: Custom header name (required when MCP4_AUTH_TYPE=custom-header)MCP4_AUTH_QUERY_PARAM: Query parameter name (required when MCP4_AUTH_TYPE=query)Example: Force bearer authentication for incomplete spec:
export MCP4_AUTH_FORCE=true
export MCP4_AUTH_TYPE=bearer
export MCP4_API_TOKEN=your_token_here
export MCP4_OPENAPI_SPEC_PATH=./incomplete-spec.yaml
npm start
CLI alternative:
export MCP4_API_TOKEN=your_token_here
npm start \
--auth-force true \
--auth-type bearer \
--openapi-spec-path ./incomplete-spec.yaml
Note: If OpenAPI spec has security defined, it takes precedence over force auth settings.
MCP4_PROXY_MAX_BYTES: Global override for proxy download size limit (bytes). Must be a positive integer.max_size_bytes_from_env on a proxy_download operation.Precedence: profile-specific env override → MCP4_PROXY_MAX_BYTES → profile max_size_bytes → built-in default (10MB).
Example: Cap proxy downloads to 2MB globally
export MCP4_PROXY_MAX_BYTES=2097152
When generating tools from OpenAPI without a profile, long operation IDs may exceed limits. Configure automatic shortening:
MCP4_TOOLNAME_MAX: Maximum tool name length (default: 45)MCP4_TOOLNAME_STRATEGY: Shortening strategy: none|balanced|iterative|hash|auto (default: none)none: No shortening, only warningsbalanced: Add parts by importance until unique & meaningful (recommended)iterative: Progressively remove noise until under limit (conservative)hash: Use verb + resource + hash for guaranteed uniquenessauto: Try strategies in order: balanced → iterative → hashMCP4_TOOLNAME_WARN_ONLY: Only warn, don't shorten: true|false (default: true)MCP4_TOOLNAME_SIMILAR_TOP: How many similar operationId pairs to show in warnings (default: 3)MCP4_TOOLNAME_SIMILARITY_THRESHOLD: Similarity threshold for warning examples (default: 0.75)MCP4_TOOLNAME_MIN_PARTS: Minimum parts for balanced strategy (default: 3)MCP4_TOOLNAME_MIN_LENGTH: Minimum length in chars for balanced strategy (default: 20)Example: Apply balanced shortening (recommended):
export MCP4_TOOLNAME_STRATEGY=balanced
export MCP4_TOOLNAME_WARN_ONLY=false
Result for balanced strategy:
putApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImagesMetricImageId
→ put_alert_management_image (26 chars)
deleteApiV4ProjectsIdAlertManagementAlertsAlertIidMetricImagesMetricImageId
→ delete_alert_management_image (26 chars)
Example 2: Apply iterative shortening with 30 char limit:
export MCP4_TOOLNAME_STRATEGY=iterative
export MCP4_TOOLNAME_WARN_ONLY=false
export MCP4_TOOLNAME_MAX=30
MCP4_HOST: Bind address (default: 127.0.0.1)MCP4_PORT: Port (default: 3003)MCP4_ALLOWED_ORIGINS: Comma-separated origins (supports exact, wildcard *.domain.com, CIDR 192.168.1.0/24)MCP4_SESSION_TIMEOUT_MS: Session timeout (default: 1800000 = 30min)MCP4_OAUTH_SESSION_TIMEOUT_MS: OAuth session timeout for sessions with refresh tokens (default: 86400000 = 24h, 0 = unlimited)MCP4_OAUTH_REFRESH_THRESHOLD_MS: Refresh access tokens this many ms before expiry (default: 60000 = 60s)MCP4_HEARTBEAT_ENABLED, MCP4_HEARTBEAT_INTERVAL_MS: SSE heartbeat settingsMCP4_TOKEN_MAX_LENGTH: Maximum token length in characters (default: 4096, raised from 1000 in Phase 03.4 to accommodate encrypted token envelopes)MCP4_TOKEN_KEY: Optional symmetric key for AES-256-GCM encrypted token envelopes. When set, the gateway issues mcp4.v1.* tokens to OAuth clients on /oauth/token and rehydrates sessions from them on restart, eliminating the re-authentication round-trip in k8s restart scenarios. Accepts any passphrase (SHA-256-derived) or a 64-char hex string (32 raw bytes). Default unset (plain-token mode, backward-compatible). See docs/HTTP-TRANSPORT.md -> Encrypted Token Envelopes for details.MCP4_FILTER_MAX_VALUES: Max values per filtering key (default: 10)MCP4_HTTP_PROFILE_ROUTING: Enable profile routing (/profile/:id/mcp). If enabled without a default profile, /mcp is not registered.MCP4_HTTP_PROFILE_INDEX: Enable profile index on GET / for routed profiles.MCP4_PROFILES_DESCRIPTION: Optional JSON object mapping profile id/name/alias to an admin-supplied HTML snippet shown in the HTML profile detail card before the profile description. Parsed once at startup, ignored for JSON index responses, and rejected on invalid JSON, non-string values, duplicate resolution conflicts, or values longer than 10000 characters.MCP4_ALLOW_PROFILES: Comma-separated profile ids/names/aliases allowed for routed profiles.MCP4_ALLOW_PROFILES_REGEX: Regex for allowed profile ids/names/aliases (applies only when routing is enabled).MCP4_HIDDEN_PROFILES: Comma-separated profile ids/names/aliases to hide from the index page (profiles remain fully functional).MCP4_HTTP_TENANTS_FILE: Path to tenant selector config JSON.MCP4_HTTP_TENANTS_JSON: Inline tenant selector config JSON.MCP4_HTTP_TENANTS_ALLOW_HTTP: Allow http tenant selectors (default is https only).Profile routing example:
export MCP4_TRANSPORT=http
export MCP4_HTTP_PROFILE_ROUTING=true
export MCP4_HTTP_PROFILE_INDEX=true
export MCP4_ALLOW_PROFILES=gitlab-optimized,youtrack-optimized
export MCP4_PROFILES_DIR=./profiles
npx mcp4openapi
CLI alternative:
npx mcp4openapi --transport http \
--http-profile-routing true \
--http-profile-index true \
--allow-profiles gitlab,github \
--profiles-dir ./profiles
Test with curl:
curl -X POST http://localhost:3003/profile/mcp-profile-name/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"initialize"}'
Profile index admin descriptions:
export MCP4_HTTP_PROFILE_ROUTING=true
export MCP4_HTTP_PROFILE_INDEX=true
export MCP4_PROFILES_DESCRIPTION='{"gitlab":"<p><strong>Internal:</strong> Use SSO token.</p>","youtrack":"<p>Use permanent token from Hub.</p>"}'
Notes:
profileId, profileName, and aliases.GET /, not in the JSON payload.If MCP4_PROFILE_PATH (or --profile-path) is set, /mcp remains available alongside /profile/:id/mcp.
Tenant selection is configured via MCP4_HTTP_TENANTS_FILE or MCP4_HTTP_TENANTS_JSON and supports both:
https://team-a.example.com/apimask:https://grafana.*.security.*.ops.iszn.cz/apimask:https://monitoring.ops.iszn.cz/*/api (* matches exactly one path segment)Selection headers (initialize request):
X-Mcp4-Tenant-Id: selects tenant by tenant_idX-Mcp4-Api-Base-Url: selects concrete tenant endpoint by exact or mask: selectorRequired tenant scoping:
profile_ids: required non-empty array of profile ids where the tenant is activeResolution order:
X-Mcp4-Tenant-IdX-Mcp4-Api-Base-Urlmask: X-Mcp4-Api-Base-UrlRules:
mask: tenant selection, concrete X-Mcp4-Api-Base-Url is required.When MCP4_HTTP_PROFILE_INDEX=true, the HTML profile index shows tenant availability per profile and provides interactive tenant picker for supported remote snippet formats that inject X-Mcp4-Tenant-Id into copied snippet output. Picker always includes a "no tenant" option that keeps snippets without tenant headers. For mask: tenants, copied snippets also include example X-Mcp4-Api-Base-Url with wildcard parts replaced by <your-part>. In Local stdio mode, tenant selection updates API base URL in snippets that support local env injection (using profile API endpoint env var). The same page also exposes a per-profile tool catalog with interactive builders for X-Mcp4-Tools and X-Mcp4-Params: in remote mode, unsupported custom-header snippet variants are hidden while filtering is active; in local mode, the same filter state is translated into --tool-filter-allow-names, --tool-filter-allow-categories, and --param-filter inside generated stdio snippets. Profiles that use auth.type: "session-cookie" are intentionally shown only in Local stdio snippets because remote HTTP initialization does not accept upstream login/password via request headers.
X-Mcp4-Params is a per-session header for constraining tool call parameters (not tool selection). It is parsed on session initialization and then enforced for the lifetime of the session: subsequent requests may omit the header, but if provided it must match the session value or the server returns a 400 validation error. If MCP4_PARAM_FILTER is also set, the session header may only narrow that process-wide baseline.
Format: comma-separated key=value pairs. Repeat keys to allow multiple values.
Example for GitLab profile:
X-Mcp4-Params: project_id=123, project_id=mcp/mcp-gitlab, _allow_list, _allow_read
What this means:
123 or mcp/mcp-gitlab (both refer to the same project) for tools that accept project_id (or an alias mapped to it). If a tool call provides a different project_id, the server rejects it._allow_list and _allow_read relax filter enforcement for list and read operations; use them if you want list/read calls to be allowed even when they omit the filtered key, or when they pass a different value.Notes:
MCP4_FILTER_MAX_VALUES._allow_list: allows list operations to omit the filtered key (only affects presence enforcement)._allow_read: allows read operations to omit the filtered key (only affects presence enforcement).key=value filter is present (otherwise there is nothing to enforce).See docs/HTTP-TRANSPORT.md for detailed HTTP transport configuration.
MCP4_SSL_CERT_FILE, MCP4_SSL_KEY_FILE: SSL certificate and key (PEM format)When both are set, server automatically starts in HTTPS mode.
See docs/OAUTH.md for SSL configuration with OAuth.
OAuth requires HTTP transport. Stdio (command/args) client configuration does not support OAuth browser flow.
Cursor OAuth setup (global user config) example:
{
"mcpServers": {
"gitlab-oauth": {
"url": "http://127.0.0.1:3003/mcp"
}
}
}
Autodiscovery - Just provide DCR (Dynamic Client Registration) credentials, API base URL and OAuth callback:
export MCP4_TRANSPORT=http
export MCP4_HOST=127.0.0.1
export MCP4_PORT=3003
export MCP4_API_BASE_URL=https://www.gitlab.com/api/v4
export MCP4_OAUTH_CLIENT_ID=your_dcr_client_id
export MCP4_OAUTH_CLIENT_SECRET=your_dcr_client_secret
export MCP4_OAUTH_REDIRECT_URI=http://127.0.0.1:3003/oauth/callback
# OAuth endpoints are automatically discovered from API base URL
Note: DCR and OAuth callback must be registered with the OAuth provider.
Configuration priority:
MCP4_OAUTH_AUTHORIZATION_URL, MCP4_OAUTH_TOKEN_URL (highest priority)MCP4_OAUTH_ISSUER (auto-derives standard OAuth paths)MCP4_API_BASE_URL (fetches RFC 8414 metadata or uses standard paths)Environment variables:
MCP4_OAUTH_CLIENT_ID, MCP4_OAUTH_CLIENT_SECRET: OAuth client credentials (required)MCP4_OAUTH_REDIRECT_URI: OAuth redirect URI (required, must match registered URI)MCP4_ALLOW_UNREGISTERED_CLIENTS: Allow authorize requests for unregistered OAuth clients when redirect URIs match the approved allowlist (optional, default: false)MCP4_ALLOWED_UNREGISTERED_REDIRECT_URIS: Comma-separated approved redirect URI rules for unregistered OAuth clients, e.g. http://localhost,cursor:// (optional)MCP4_OAUTH_ISSUER: OAuth provider issuer URL (optional, auto-derives endpoints)MCP4_OAUTH_AUTHORIZATION_URL, MCP4_OAUTH_TOKEN_URL: OAuth endpoints (optional, for non-standard paths)MCP4_OAUTH_CLIENT_STORE_MAX_CLIENTS: Max dynamic OAuth clients stored in memory (default: 1000)MCP4_OAUTH_CLIENT_STORE_MAX_REDIRECT_URIS: Max redirect_uris per dynamic client (default: 10)MCP4_OAUTH_CLIENT_STORE_MAX_REDIRECT_URI_LENGTH: Max length of one redirect URI (default: 256)MCP4_OAUTH_CLIENT_STORE_IDLE_GRACE_MS: Minimum age (ms) before an idle OAuth client is evictable (default: 0)CLI equivalents:
--allow-unregistered-clients true--allowed-unregistered-redirect-uris http://localhost,cursor://Dynamic client store eviction behavior:
mcp-client-*) and does not evict clients that are currently active in session/state/code flows./oauth/register returns 429 with temporarily_unavailable.See docs/OAUTH.md for complete setup guide including OAuth application registration, SSL configuration, and troubleshooting.
MCP4_HTTP_RATE_LIMIT_ENABLED: Enable rate limiting (default: true)MCP4_HTTP_RATE_LIMIT_WINDOW_MS: Rate limit window (default: 60000 = 1 minute)MCP4_HTTP_RATE_LIMIT_MAX_REQUESTS: Max requests for MCP endpoints (default: 100)MCP4_HTTP_RATE_LIMIT_METRICS_MAX: Max requests for /metrics (default: 10)OAuth Rate Limiting (stricter limits for OAuth endpoints):
MCP4_OAUTH_RATE_LIMIT_MAX: Max OAuth requests per window (default: 10)MCP4_OAUTH_RATE_LIMIT_WINDOW_MS: OAuth rate limit window (default: 60000 = 1 minute)Configuration Priority: Profile > Environment variables > Defaults
Defaults:
/oauth/authorize, /oauth/token, /oauth/callback)Returns 429 Too Many Requests when exceeded.
MCP4_LOG_LEVEL: debug, info (default), warn, errorMCP4_LOG_FORMAT: console (default) or jsonMCP4_METRICS_ENABLED: Enable Prometheus metrics (default: false)MCP4_METRICS_PATH: Metrics endpoint (default: /metrics)profile_id and tenant_id labels; when unresolved they use profile_id="unknown" and tenant_id="none".Security Note:
Internal error) while full details are logged server-sideProfile defines which MCP tools from OpenAPI spec are exposed and how to aggregate them.
Start with existing profiles from profiles/ (e.g., GitLab).
Features:
Create your own profiles: See docs/PROFILE-GUIDE.md
npm run validate
# Checks: JSON syntax, schema, logic, OpenAPI operations
npm run validate:schema
# Validates profile-schema.json itself
npm test
npm run test:e2e
Cursor:
VS Code:
JetBrains IDEs:
<your_mcp_server>.log for MCP-related errorsCommon Issues:
profiles/ - Example profiles for OpenAPI specsprofiles/youtrack/ - YouTrack profile + bundled OpenAPI spec (ready-to-use MCP tools)profiles/codecov/ - Codecov CRUD-style profile + bundled OpenAPI specprofile-schema.json - JSON Schema for IDE autocompleteSee CONTRIBUTING.md for development guidelines.
Run in your terminal:
claude mcp add mcp4openapi -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.