跳到正文
GitHub·· 7 天前AI 评分41

mcpfather:从 OpenAPI 规范生成企业级 MCP 服务器的生成器

flowgent-labs/mcpfather

AI 导读

flowgent-labs 发布 mcpfather,一款可从 OpenAPI 2.x/3.x(JSON 或 YAML)规范一键生成生产级 MCP 服务器的生成器,每个 API 操作都会变成带类型化输入输出 schema 的 MCP 工具。

正文

Build & Test Go Version License OpenAPI MCP OIDC Prometheus OpenTelemetry Helm

An Enhanced enterprise-grade MCP generator / builder — generates production-ready MCP servers from OpenAPI specs, Each API operation becomes an AI-callable tool with typed schemas and customized aggregate virtual tools(Reduce tokens consumption), auth forwarding, and helm chart deployment and OTEL observability, and even use as regular CLI in development.

Features

  • OAS 2.x / 3.x support — JSON or YAML, one-command generation. Every OpenAPI operation becomes a typed MCP tool with structured input/output schemas.
  • Virtual Tools — Declaratively compose native tools into pipelines (e.g call → jq → foreach → emit → return). Drastically reduces LLM token consumption for multi-step API workflows.
  • Enterprise Auth — Frontend OIDC JWT bearer validation (RFC 9728 Resource Server), plus backend OIDC (client credentials + password grants), and static web/cookie tokens for upstream APIs. Frontend and backend credentials are fully decoupled per the MCP Token Passthrough Prohibition.
  • Prometheus Metrics — Standard mcp_tool_call_duration_seconds histogram exported for every native and virtual tool invocation, with configurable boundaries and static labels.
  • OTel Distributed Tracing — Optional OpenTelemetry tracing via OTLP gRPC (-tags otel). W3C trace context is propagated to upstream APIs for end-to-end visibility across agent teams.
  • Deployment Artifacts — Generated projects ship with Dockerfile, Helm chart, Makefile targets, and K8s manifests (ConfigMap, Secret, HPA, Ingress/Gateway, SecretProviderClass for GCP).
  • TFS Data Plane Server — Built-in REST endpoints (/_/tfs/*) for binary file upload and download, cleanly separated from the JSON-RPC 2.0 control plane at /mcp. OpenAPI file transfer operations become MCP tools that route binary payloads through the data plane, not the control channel.

Quick Start

Build Generator

make

Generate MCP server (e.g: Confluence)

./bin/mcpfather -v \
    -i use-cases/swaggers/confluence-server-v10.2.14.oas.v3.0.1.json \
    -o use-cases/confluence-mcp \
    --includes "listSpaces,createPage,updatePage,deletePage"

Start in HTTP mode (example)

  • The server defaults to httpbin.org which echoes requests — great for quick verification:
export MCP__UPSTREAM__DEFAULT__ENDPOINT=https://api.example.com

# Optional 1: setup token from env
export MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN=your-token
use-cases/confluence-mcp/bin/confluence-mcp -v 10 --transport http --port 8080

# Optional 2: setup token from file (e.g: echo -n "YOUR_TOKEN" > /path/to/.credentials)
export MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE=/path/to/.credentials
use-cases/confluence-mcp/bin/confluence-mcp -v 10 --transport http --port 8080
  • Test with mcpclient.sh (for HTTP transport only)
./mcpclient.sh list-tools
./mcpclient.sh call GetPage '{"id": "123456"}'
  • Inspection MCP frontend authentication (OAuth2.1).
# Start the MCP server with HTTP mode.
export MCP__SERVER__AUTH__OIDC__ENABLED=true
export MCP__SERVER__AUTH__OIDC__ISSUER="https://keycloak.example.com/realms/master"
export MCP__SERVER__AUTH__OIDC__AUDIENCE="confluence-mcp"
./bin/confluence-mcp -v 10 --transport http --port 8080

# Obtain the OAuth2.1 metadata.
curl -s https://iam.example.com/realms/master/.well-known/openid-configuration

curl -s localhost:8080/.well-known/oauth-protected-resource
#{"resource":"confluence-mcp","authorization_servers":["https://keycloak.example.com/realms/master"],"bearer_methods_supported":["header"]}

Run in CLI Mode (example)

Invoke tools directly from the command line — no MCP agent needed. Useful for debugging, scripting, and manual API exploration. The CLI reuses the same mcptools handlers as the MCP server, so every call makes a real HTTP request upstream.

# Set your upstream endpoint (required for real API calls)
export MCP__UPSTREAM__DEFAULT__ENDPOINT=https://api.example.com
export MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN=your-token

# First call: list available tools
use-cases/confluence-mcp/bin/confluence-mcp -t cli list

# First tool call: fetch a page by ID
use-cases/confluence-mcp/bin/confluence-mcp -t cli Getpage --id 123456

# Show tool-specific help (GNU-style usage)
use-cases/confluence-mcp/bin/confluence-mcp -t cli Getpage --help

# Call a tool with GNU-style --flag arguments
use-cases/confluence-mcp/bin/confluence-mcp -t cli ListSpaces --limit=5 --type global
use-cases/confluence-mcp/bin/confluence-mcp -t cli SearchContent --cql 'type=page AND text~"API"' --limit 10

# Call a tool without arguments (for tools that have no required params)
use-cases/confluence-mcp/bin/confluence-mcp -t cli ListSpaces

Generator Self Configuration

./bin/mcpfather -i spec.yaml -o output-dir [--includes op1,op2] [--excludes op3] [-v]
Flag Description Example
-i, --input Path to the OpenAPI specification file (JSON or YAML) spec.yaml
-o, --output Path to the output MCP server directory ./my-mcp
--includes Comma-separated operationId values to generate (omit for all) listSpaces,createPage
--excludes Comma-separated operationId values to skip healthCheck,status
-v, --verbose Print step-by-step generation details
--validation Enable OpenAPI schema validation

Values are matched against the operationId field in the OpenAPI spec (exact string match). An operationId appearing in both --includes and --excludes triggers an error.

Filtering

Use --includes and --excludes to control which operations generate MCP tools. Values are the operationId strings from your OpenAPI spec.

  • for example - Generate the Atlassian Confluence MCP server
# Only generate tools for specific operations
./bin/mcpfather -i use-cases/swaggers/confluence-server-v10.2.14.oas.v3.0.1.json \
    -o use-cases/confluence-mcp --includes "listSpaces,createPage,getSpaceContent"

# Generate all tools except health checks
./bin/mcpfather -i use-cases/swaggers/confluence-server-v10.2.14.oas.v3.0.1.json \
    -o use-cases/confluence-mcp --excludes "healthCheck,status"

# Generate all tools except a few
./bin/mcpfather -i use-cases/swaggers/confluence-server-v10.2.14.oas.v3.0.1.json \
    -o use-cases/confluence-mcp --excludes "uploadAttachment,removeLabel"

# Preview what gets included/excluded
./bin/mcpfather -i use-cases/swaggers/confluence-server-v10.2.14.oas.v3.0.1.json \
    -o use-cases/confluence-mcp --includes "listSpaces" -v

Tool name truncation

Long operationId values are automatically truncated to 125 characters with a hash suffix to preserve uniqueness, ensuring compatibility with MCP tool name limits.

Generated MCP Server - Configuration

Flag Description Default
--transport <stdio|http|cli> Transport mode stdio
-p, --port <number> HTTP server port 8080
-v, --verbose <0-10> Request logging verbosity 0
--print-default-config Print default config.yaml to stdout and exit

Logging levels

Level Output
0 Silent
1 HTTP access log: [http] sid=- 200 POST /mcp (1ms)
2 MCP request log: [mcp] tool=SearchContent args={...}, upstream method + URL
3 + upstream query params
5 + request/response headers
7 + request/response body
9 + pretty-printed JSON body
10 Same as 9 (full debug)

TFS — Temporary File System (Data Plane)

MCP speaks JSON-RPC 2.0 at /mcp — a control plane that carries structured tool invocations. But OpenAPI specs often include file download/upload operations that transfer raw binary payloads. Pushing multi-megabyte blobs through JSON-RPC is inefficient and breaks streaming semantics.

MCPFather solves this with a dual-plane architecture:

Plane Protocol Endpoint Purpose
Control JSON-RPC 2.0 /mcp Tool discovery, typed arguments, structured results
Data REST /_/tfs/* Binary file upload/download with UUID collision avoidance

How it works:

  1. Generator stage — MCPFather detects OpenAPI operations that produce/consume binary content (e.g. produces: application/octet-stream, multipart form upload). These become MCP tools that return a FileRef (file:// URI) instead of inline base64 data.

  2. At runtime — When an AI agent calls a download tool, the MCP server fetches the binary from the upstream API, stores it to ~/.{app}/tfs/download/{yyyyMMdd}/{uuid}.{suffix}, and returns a JSON result containing the TFS download URL:

    {"fileRef": "http://localhost:8080/_/tfs/download/20260808/a1b2c3d4-....pdf"}
  3. Upload reverse — The MCP client uploads a file via POST /_/tfs/upload/{yyyyMMdd}/{uuid}.{suffix}, the tool invocation receives the file path, and the server forwards the binary upstream.

UUID-based naming prevents collisions when the same file is downloaded or uploaded multiple times. Files are organized by date under ~/.{app}/tfs/download/{yyyyMMdd}/.

Configuration (config.yaml):

server:
  tfs:
    enabled: true   # set false to disable the data plane (pure JSON-RPC mode)

The TFS REST API is part of the same HTTP server (same port) as /mcp. No additional ports or services needed.

Environment variables

Auth Layers at a Glance — frontend validates inbound, backend authenticates outbound:

Layer Config YAML path Env var prefix Role
Server server.auth.oidc MCP__SERVER__AUTH__OIDC__* Validates AI agent bearer tokens (inbound)
Upstream OIDC upstream.default.auth.oidc MCP__UPSTREAM__DEFAULT__AUTH__OIDC__* Server's own OIDC client_credentials for upstream APIs
Upstream Static upstream.default.auth.static MCP__UPSTREAM__DEFAULT__AUTH__STATIC__* Server's own static token/cookie for upstream APIs

The AI agent's inbound token is never forwarded upstream (MCP spec: Token Passthrough Prohibition).

Frontend (inbound) env vars:

Variable Description
MCP__SERVER__AUTH__OIDC__ENABLED Enable JWT bearer validation for inbound requests
MCP__SERVER__AUTH__OIDC__ISSUER OIDC issuer for agent tokens (used for JWKS discovery)
MCP__SERVER__AUTH__OIDC__JWKS_URI JWKS endpoint (auto-discovered from issuer if empty)
MCP__SERVER__AUTH__OIDC__AUDIENCE Expected aud claim; also the RFC 9728 resource identifier

Backend (outbound) env vars:

Variable Description
MCP__UPSTREAM__DEFAULT__ENDPOINT Base URL of the upstream API (default: https://httpbin.org/anything)
MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_ID OIDC client ID for upstream authentication
MCP__UPSTREAM__DEFAULT__AUTH__OIDC__CLIENT_SECRET OIDC client secret for upstream authentication
MCP__UPSTREAM__DEFAULT__AUTH__OIDC__ISSUER OIDC issuer for upstream token acquisition
MCP__UPSTREAM__DEFAULT__AUTH__OIDC__SCOPES OIDC scopes (default: openid)
MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN Static web token for upstream auth
MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE Path to a file containing the web token
MCP__UPSTREAM__DEFAULT__AUTH__STATIC__COOKIE_TOKEN Cookie token for upstream session auth
MCP__UPSTREAM__DEFAULT__AUTH__STATIC__COOKIE_TOKEN_FILE Path to a file containing the cookie token
... ...

Token retrieval priority (backend / outbound)

The server tries to obtain an upstream Bearer token in this order:

  1. OIDC client_credentials grant (upstream.default.auth.oidc.*)
  2. Static web token (upstream.default.auth.static.web_token or web_token_file)

The AI agent's own Authorization header is deliberately excluded from upstream forwarding (MCP spec: Token Passthrough Prohibition).

Token format

  • The token value is inspected for a recognized prefix. If the value already starts with Bearer or Basic (case-insensitive), it is used as-is in the Authorization header. Otherwise, Bearer is automatically prepended.

Tool filtering

  • For specs with many operations, limit which tools AI agents can discover via an optional config file:
# Print the default config template
use-cases/confluence-mcp/bin/confluence-mcp --print-default-config

# Edit: ~/.confluence-mcp/config.yaml and list only the tools you want
  • $HOME/.{serviceName}/config.yaml:
# ---- Native MCP Tools ----
native_tools:
  expose:
    # When true, all native tools are registered by default
    # (individual tools can be hidden via excludes).
    # When false (the default), only tools listed in includes
    # are exposed.
    register_all_tools_by_default: false

    # Explicitly expose these tools (operationId values).
    # Takes precedence: tools listed here are always exposed,
    # even if register_all_tools_by_default is false.
    includes:
      - ListSpaces
      - SearchContent

    # Explicitly hide these tools from external agents (operationId values).
    # Takes precedence over register_all_tools_by_default.
    # A tool listed in BOTH includes and excludes will cause
    # the server to fail at startup.
    excludes: []
  • When tools.expose.include is non-empty, only those tools are registered with the MCP server and shown in -t cli list. When absent or empty, all tools are available.

Virtual Tools (Composition)

~/.test-verify-v2/config.yaml:

# ---- Virtual Tools ----
# Compose multiple native tools into a single virtual tool via a declarative
# e.g: 5-step pipeline (call → jq → foreach → emit → return).
# Schema: https://github.com/flowgent-labs/mcpfather/blob/main/.agents/skills/virtual-tool-creator/resources/dsl-schema.json
virtual_tools:
  - id: getData
    kind: call
    spec:
      tool: GetData
      parse: json
      args:
        id: $input.dataId
  - id: enrich
    kind: foreach
    spec:
      in: $getData.items
      as: item
      concurrency: 8
      preserveOrder: true
      pipeline:
        - id: getDetail
          kind: call
          spec:
            tool: GetItemDetail
            args:
              id: $item.id
        - id: emitEnriched
          kind: emit
          spec:
            from: $item
            vars:
              detail: $getDetail
            expr: '. + {detail: $detail}'
  - id: done
    kind: return
    spec:
      from: $enrich
  • Pipeline step kinds: call (invoke an MCP tool), http (direct HTTP API call on a named upstream), jq (jq expression transform), foreach (concurrent iteration over arrays), emit (output within foreach), and return (final result). Full documentation in .agents/skills/virtual-tool-creator/.
  • HTTP step outputs use {body, headers}; reference payloads as $stepId.body and response headers as $stepId.headers.<Header-Name>.

HTTP node connection pool, timeout, and retry

Define reusable policies once and select them from an HTTP node. dial_timeout limits TCP connection establishment; request_timeout limits one complete attempt, including reading the response body. Retry has its own total budget.

middleware:
  http_client_pool:
    large:
      max_idle_conns: 128          # reusable idle connections across all upstream hosts
      max_idle_conns_per_host: 32  # reusable idle connections retained per upstream host
      max_conns_per_host: 64       # hard cap: active + dialing + idle connections per host
      dial_timeout: 10s            # TCP connection establishment timeout
      request_timeout: 60s         # complete attempt, including response-body reads
    medium:
      max_idle_conns: 64
      max_idle_conns_per_host: 16
      max_conns_per_host: 32
      dial_timeout: 5s
      request_timeout: 30s
    small:
      max_idle_conns: 16
      max_idle_conns_per_host: 4
      max_conns_per_host: 8
      dial_timeout: 3s
      request_timeout: 15s
  retry:
    reliable:
      max_retries: 4               # extra attempts after the first request
      max_elapsed_time: 30s        # hard budget for all attempts and backoff
    standard:
      max_retries: 2
      max_elapsed_time: 15s
    besteffort:
      max_retries: 0

# Select one policy from each group in an HTTP pipeline step:
virtual_tools:
  - name: fetch_issues
    input_schema: {type: object}
    pipeline:
      - id: request
        kind: http
        spec:
          upstream: default
          pool: medium
          retry: standard
          method: GET
          path: /api/issues
      - id: done
        kind: return
        spec:
          from: $request.body

The QoS-style names communicate retry intent without promising application-level success. Omitted references use process-wide built-ins: pool limits 32/32/32, disabled request timeout, and max_retries: 0.

Generated MCP Server - Agent Integration

OpenCode

  • ~/.config/opencode/opencode.json:
{
  "mcp": {
    "confluence-mcp": {
      "type": "local",
      "command": ["bash", "-c", "/path/to/confluence-mcp"],
      "args": ["--transport", "stdio"],
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      },
      "enabled": true
    }
  }
}

Claude Code

  • ~/.claude.json:
{
  "mcpServers": {
    "confluence-mcp": {
      "command": "/path/to/confluence-mcp",
      "args": ["--transport", "stdio"],
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      }
    }
  }
}

Codex CLI

  • ~/.codex/config.toml:
[mcp_servers.confluence-mcp]
url = "http://localhost:8080/mcp"
web_token_env_var = "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN"

Cursor

  • ~/.cursor/mcp.json:
{
  "mcpServers": {
    "confluence-mcp": {
      "command": "/path/to/confluence-mcp",
      "args": ["--transport", "stdio"],
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      }
    }
  }
}

OpenCode (Remote)

  • ~/.config/opencode/opencode.json:
{
  "mcp": {
    "confluence-mcp": {
      "type": "remote",
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      }
    }
  }
}

Claude Code (Remote)

  • ~/.claude.json (User MCPs):
{
  "mcpServers": {
    "confluence-mcp": {
      "url": "http://localhost:8080/mcp",
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      }
    }
  }
}

Codex CLI (Remote)

  • ~/.codex/config.toml:
[mcp_servers.confluence-mcp]
url = "http://localhost:8080/mcp"
web_token_env_var = "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN"

Cursor (Remote)

  • ~/.cursor/mcp.json:
{
  "mcpServers": {
    "confluence-mcp": {
      "url": "http://localhost:8080/mcp",
      "env": {
        "MCP__UPSTREAM__DEFAULT__ENDPOINT": "https://api.example.com",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN": "your-token",
        "MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN_FILE": "/path/to/fallback/.credentials"
      }
    }
  }
}

Docker Deployment

The generated Docker image is a static binary on scratch — no shell, no tools. Configure via environment variables and a volume-mounted config file.

# 1. Prepare config
mkdir -p ~/.my-mcp-server
cp config.yaml ~/.my-mcp-server/config.yaml

# 2. Run (HOME is required — the server resolves $HOME/.<serviceName>/config.yaml)
docker run -d --name my-mcp-server \
    --restart unless-stopped \
    -e HOME=/home/mcp \
    -e MCP__UPSTREAM__DEFAULT__ENDPOINT="https://api.example.com" \
    -e MCP__UPSTREAM__DEFAULT__AUTH__STATIC__WEB_TOKEN="your-token" \
    -v ~/.my-mcp-server:/home/mcp/.my-mcp-server \
    -p 8080:8080 -p 9991:9991 \
    ghcr.io/<YOUR_ORG>/my-mcp-server:v1.0.0

Note: -e HOME=/home/mcp is mandatory. The scratch image has no environment variables; without HOME, os.UserHomeDir() fails and the server exits immediately.

Helm Deployment

Generated MCP servers ship with an embedded Helm chart under deploy/helm/. The official Docker image is published to GitHub Container Registry on every release.

# Install a generated MCP server from the ghcr.io image
helm upgrade --install --create-namespace \
  my-mcp-server ./deploy/helm \
  --set image.repository=ghcr.io/<YOUR_ORG>/my-mcp-server \
  --set image.tag=v1.0.0 \
  --set config.upstream.default.endpoint=https://api.example.com \
  --set config.upstream.default.auth.static.create=true \
  --set config.upstream.default.auth.static.webToken=<YOUR_TOKEN>

The Helm chart sets ENV HOME=/home/mcp via the Docker image and mounts the config at /home/mcp/.<serviceName>/config.yaml automatically.

Images are automatically built and pushed to e.g: ghcr.io/<YOUR_ORG>/my-mcp-server on every tagged release (feat:, fix:, refactor: commits to main).

References swaggers

Atlassian - Jira

Atlassian - Confluence

Sonatype - IQ

Sonatype - Nexus Repository

Sonarqube

Github

Telegram

Binance

License

This project is licensed under the AGPL License, but the Generated MCP servers exception, It will use a permissive standard Apache License 2.0. — see the LICENSE file for details.

Contact

For questions, suggestions, or support:

Acknowledgments

This MCP server was generated by MCPFather, an enterprise-grade OpenAPI-to-MCP code generator.

Built with these excellent open-source projects:

  • mcp-go — Go SDK for the Model Context Protocol
  • OpenTelemetry — observability framework for metrics and tracing
  • Prometheus — metrics collection and alerting
  • Viper — Go configuration management
  • go-jq — Pure Go implementation of jq
  • Keycloak — Open Source Identity and Access Management

来源:GitHub · github.com