Back to Discover

manifold

connector

nonchan7720

MCP gateway aggregating MCP servers and OpenAPI/Swagger REST APIs behind one MCP endpoint

View on GitHub
0 starsSynced Aug 3, 2026

Install to Claude Code

/plugin marketplace add nonchan7720/manifold

README

Manifold

One interface. Many connections. Manifold.

CI Release Go Report Card License: MIT

English | 日本語

Manifold is a gateway that acts as an MCP server while connecting to multiple external MCP servers and OpenAPI / Swagger-compliant REST APIs on the backend.

Why "Manifold"?

The name Manifold comes from an engine's intake manifold.

An intake manifold is the component that distributes air and fuel evenly and efficiently from a single inlet to multiple cylinders. We named this project Manifold because its structure is similar.

Engine manifoldThis project
Single inletRequests from MCP clients
Distribution / routingProtocol conversion / routing
To multiple cylindersTo multiple external MCP / REST APIs

Architecture

MCP Client
    │
    ▼
┌─────────────┐
│   Manifold  │   ← this server
└─────────────┘
    │       │
    ▼       ▼
External  OpenAPI / Swagger
MCP       REST API Server
Server

Features

  • OpenAPI / Swagger → MCP conversion: Automatically generates MCP tools from OpenAPI 3.x / Swagger 2.x specifications
  • MCP backend aggregation: Transparent reverse proxy to external MCP servers
  • Built-in OAuth 2.1 server: Authorization server with PKCE (S256) support
  • Pluggable backend authentication: Choose one of static header (authValue) / OAuth 2.0 (oauth2) / API key Token Exchange (tokenExchange)
  • Resource links: Stores binary content from tool responses in S3 and returns download URLs (resource links)
  • Lazy connection: Connects to backends on first request (no backend dependency at gateway startup)
  • Selectable storage: Session / token management backed by Redis or SQLite
  • OpenTelemetry support: OTLP export of traces, metrics, and logs (metrics also support Prometheus-style pull)

Requirements

  • Go 1.26+
  • Redis or SQLite (for session management)

Installation

Download binary

Download the latest binary from Releases.

Build from source

git clone https://github.com/nonchan7720/manifold.git
cd manifold
go build -o manifold .

Docker

docker pull ghcr.io/nonchan7720/manifold:latest

Usage

Start the gateway

# Run the binary
manifold gateway

# Specify a config file explicitly (-c / --config, config name without extension)
manifold gateway -c config

# Run from source
go run main.go gateway

# Docker (working directory is /home/nonroot)
docker run -p 9999:9999 \
  -v $(pwd)/config.yaml:/home/nonroot/config.yaml \
  ghcr.io/nonchan7720/manifold:latest

Docker Compose (development)

Starts a development environment including Redis.

docker compose up -d

Ready-to-run configuration examples are available in the examples/ directory.

Configuration

Place a configuration file (config.yaml) in the current directory or in a config/ subdirectory. Configuration values support environment variable expansion in the form ${VAR} or ${VAR:-default}.

Connecting to an MCP backend

Expose an external MCP server through Manifold.

gateway:
  port: 9999
  # openssl rand -base64 32
  encryptKey: ${ENCRYPT_KEY}

mcpServers:
  my-mcp-server:
    description: External MCP server
    transport: http
    url: http://localhost:8080/mcp

sqlite:
  path: ./tmp/manifold.db

Connecting to an OpenAPI / Swagger backend

Automatically generate MCP tools from an OpenAPI specification.

gateway:
  port: 9999
  encryptKey: ${ENCRYPT_KEY}

mcpServers:
  my-api:
    description: Sample REST API
    spec: https://example.com/api/openapi.json
    baseURL: https://example.com

OpenAPI backend with OAuth 2.0 authentication

gateway:
  port: 9999
  encryptKey: ${ENCRYPT_KEY}

mcpServers:
  my-api:
    description: OAuth-protected API
    spec: https://example.com/api/openapi.json
    baseURL: https://example.com
    oauth2:
      clientID: YOUR_CLIENT_ID
      clientSecret: YOUR_CLIENT_SECRET
      authURL: https://example.com/oauth/authorize
      tokenURL: https://example.com/oauth/token
      scopes:
        - read
        - write

redis:
  addrs:
    - "${REDIS_ADDRS:-localhost:6379}"
  db: ${REDIS_DB:-0}

Configuration reference

gateway

FieldTypeDescription
portintListening port (default: 8081)
keystringTLS private key file path (optional)
certstringTLS certificate file path (optional)
encryptKeystringToken encryption key (required). Base64-encoded 32-byte AES-256 key. Generate with openssl rand -base64 32

mcpServers.<name>

Server names (<name>) are used in URL paths, so only alphanumerics, _, and - are allowed.

FieldTypeDescription
descriptionstringServer description (required; included in /mcp/list responses)
transportstringTransport for MCP backends (http or stdio)
urlstringEndpoint for the HTTP transport
commandstringCommand for the stdio transport
args[]stringArguments for the stdio command
envmap[string]stringEnvironment variables for the stdio process
specstringPath or URL of an OpenAPI/Swagger specification
baseURLstringAPI base URL in OpenAPI mode (required when spec is set)
headersmap[string]stringExtra headers added to API requests
authValueobjectStatic authentication settings (header, prefix, value)
oauth2objectOAuth 2.0 settings (see below)
tokenExchangeobjectToken Exchange settings (see below)

authValue / oauth2 / tokenExchange are mutually exclusive; only one may be configured at a time.

mcpServers.<name>.oauth2

FieldTypeDescription
clientIDstringClient ID (required)
clientSecretstringClient secret (required)
authURLstringAuthorization endpoint (required; absolute URL)
tokenURLstringToken endpoint (required; absolute URL)
scopes[]stringScopes to request

mcpServers.<name>.tokenExchange

Exchanges the API key received from the client for an OAuth token at the specified token exchange endpoint, and uses it for backend requests. Exchange results are cached, and rate limits (429) are respected.

FieldTypeDescription
urlstringAbsolute URL of the token exchange endpoint (required)

redis

FieldTypeDescription
urlstringRedis URL (e.g. redis://user:pass@localhost:6379/0)
addrs[]stringList of host:port pairs (for Cluster/Sentinel)
userstringUsername
passwordstringPassword
dbintDatabase number
master_namestringSentinel master name
tlsboolEnable TLS
cluster_modeboolEnable Cluster mode

sqlite

FieldTypeDescription
pathstringDatabase file path (:memory: for in-memory)

Either redis or sqlite must be configured.

storage

Stores content included in OpenAPI/Swagger tool responses (images, binaries, etc.) in external storage and returns resource links (download URLs). When unset, no storage is used.

FieldTypeDescription
typestringStorage type. Currently only s3 is supported
hostURLstringHost for download URLs (when set, content is served via Manifold's /media/download/{id})
s3.bucketstringS3 bucket name (required when type: s3)
s3.keyPrefixstringS3 object key prefix (required when type: s3)
storage:
  type: s3
  hostURL: https://manifold.example.com
  s3:
    bucket: my-bucket
    keyPrefix: manifold/media

fileFetch

When a URL is passed to a file input field of an OpenAPI/Swagger tool, Manifold downloads the file from that URL. As an SSRF countermeasure, connections to private/loopback/link-local IPs and the http:// scheme are rejected by default.

FieldTypeDescription
allowLocalboolAllow connections to private/loopback IPs and http:// (for testing with local stacks; default: false)
allowedHosts[]stringAllowlist of hosts (hostname, or host:port). Empty allows all hosts (private IP blocking still applies)
maxSizeint64Maximum bytes for downloaded/base64/text content. 0 or unset defaults to 524288000 (500 MiB)

Each field can also be overridden via environment variables (FILEFETCH_MAXSIZE, FILEFETCH_ALLOWLOCAL, FILEFETCH_ALLOWEDHOSTS).

fileFetch:
  allowLocal: false
  maxSize: 524288000 # 500MiB
  # allowedHosts:
  #   - example.com
  #   - files.example.com:8443

telemetry

Output settings for traces, metrics, and logs via OpenTelemetry.

FieldTypeDescription
serviceNamestringService name
environmentstringEnvironment name (deployment.environment attribute)
gzipCompressionboolGzip compression for OTLP export
traceobjectTrace settings (enabled, http, grpc)
metricsobjectMetrics settings (enabled, exporterType: push / pull, http, grpc)
logsobjectLog settings (enabled, http, grpc)

For the http / grpc exporters, specify addr (host:port) or url. grpc also accepts insecure. With metrics.exporterType: pull, Prometheus-format metrics are exposed at the /metrics endpoint instead of OTLP push.

telemetry:
  serviceName: manifold
  trace:
    enabled: true
    grpc:
      addr: localhost:4317
      insecure: true
  metrics:
    enabled: true
    exporterType: push
    grpc:
      addr: localhost:4317
      insecure: true
  logs:
    enabled: true
    grpc:
      addr: localhost:4317
      insecure: true

HTTP endpoints

The HTTP endpoints exposed by Manifold.

MCP

MethodPathDescription
POST/mcp/{server_name}MCP requests (Streamable HTTP)
GET/mcp/listList registered servers (names and descriptions)

OAuth 2.1

MethodPathDescription
GET/.well-known/oauth-authorization-server/mcp/{server_name}Authorization Server metadata
GET/.well-known/oauth-protected-resource/mcp/{server_name}Protected Resource metadata
GET/{server_name}/auth/loginRedirect to the login page
GET/{server_name}/auth/callbackOAuth callback
POST/{server_name}/auth/tokenToken issuance
POST/{server_name}/auth/clientsDynamic client registration (RFC 7591)
GET/authorize, /callbackAliases without a server name
POST/token, /registerAliases without a server name

Other

MethodPathDescription
GET/media/download/{id}Download stored content (only when storage.hostURL is set)
GET/metricsPrometheus metrics (only when telemetry.metrics.exporterType: pull)

Development

See CONTRIBUTING.md for how to set up a development environment and submit changes.

Test

make test

Lint

make lint

Inspiration

This project is inspired by the Agent / MCP Gateway of LiteLLM.

Just as LiteLLM's MCP Gateway provides a unified access point to multiple MCP servers, Manifold aims to be a gateway that connects a single MCP interface to many MCP servers / REST APIs.

License

MIT License

Rendered live from nonchan7720/manifold's GitHub README — not stored, always reflects the source repo.

1 Install Method

NameDescriptionCategorySource
oci packageInstall via oci (streamable-http transport)mcp-serverghcr.io/nonchan7720/manifold:v1.6.1

0 Comments

Login required
Log in to post a comment or update on this repo.

No comments yet — be the first to share an update.