Skip to main content
Glama
KodzghlyCZ

mcp-hooker

by KodzghlyCZ

mcp-hooker

Configurable FastMCP server that turns any OpenAPI spec (local or remote, JSON or YAML) into an MCP tool surface over HTTP.

Configuration is YAML via yayaya — layered files, dot-path lookups, and ${ENV_VAR} expansion for secrets.

Project layout

mcp-hooker/
  pyproject.toml
  config.yaml           # default config (safe to commit)
  config.local.yaml     # optional overlay (gitignored)
  Dockerfile
  docker-compose.yml
  .gitlab-ci.yml
  docs/RUNBOOK.md
  mcp_hooker/
    settings.py         # yayaya loader
    spec_loader.py      # fetch/parse OpenAPI
    route_filters.py    # openapi.tools_filter → FastMCP route_map_fn
    server.py           # reloadable HTTP MCP server

Related MCP server: OpenAPI MCP Server

Quick start

cd mcp-hooker
python -m venv .venv
source .venv/bin/activate
pip install -e .

# Edit config.yaml (openapi.spec + api.base_url), then:
mcp-hooker

The server listens on server.host / server.port from config (default 0.0.0.0:8000).

Configuration

Loaded from config.yaml, with optional config.local.yaml merged on top. Override paths with:

export MCP_HOOKER_CONFIG_FILES=config.yaml,config.docker.yaml

Keys

Path

Description

server.name

MCP server display name

server.instructions

Optional MCP initialize instructions string (injected into LLM context)

server.website_url

Optional MCP server website URL

server.version

Optional MCP server version string

server.host

Bind address

server.port

Bind port

openapi.spec

Remote URL or local path to OpenAPI JSON/YAML

openapi.fetch_timeout

Timeout when downloading remote specs (seconds)

openapi.patch_files

Local YAML/JSON overlays deep-merged into the parsed OpenAPI spec, resolved relative to the primary config file

openapi.validate_output

When false, disable FastMCP strict output-schema validation on tool responses (default true)

openapi.tools_filter

Per-instance OpenAPI operation filter (enabled, optional file, or inline rules). See examples/tools_filter.example.yaml

openapi.sanitizer.enabled

Inline local response-schema refs before FastMCP conversion

openapi.sanitizer.on_unresolved

preserve or replace_generic when local refs still cannot be resolved

openapi.sanitizer.paginated_lists.enabled

Rewrite GET list endpoints (page/per params) from bare arrays to paginated object envelopes

openapi.sanitizer.paginated_lists.items_key

Name of the array field in paginated responses (default results)

api.base_url

Upstream API base URL (falls back to servers[0].url in the spec)

api.timeout

httpx timeout for tool calls

api.headers

Extra request headers; values support ${ENV_VAR}

reload.token

If set, POST /admin/reload requires Authorization: Bearer <token>

reload.interval_seconds

Auto-reload interval (0 = off)

reload.on_sighup

Reload on SIGHUP (default true)

Example api.headers with a secret from the environment (this is how the Caflou instance authorizes upstream requests):

api:
  base_url: https://app.caflou.com
  headers:
    Authorization: "Bearer ${CAFLOU_API_TOKEN}"

Example sanitizer settings for problematic OpenAPI response schemas:

openapi:
  sanitizer:
    enabled: true
    on_unresolved: replace_generic
    paginated_lists:
      enabled: true
      items_key: results

The sanitizer only touches response schemas. It inlines local #/components/schemas/... refs before handing the spec to FastMCP. If recursive or otherwise unresolved local refs remain, replace_generic swaps the affected response schema for a generic object so MCP clients can still load the tool.

When paginated_lists.enabled is true, GET operations that accept page or per query parameters and declare a bare JSON array response are rewritten to a minimal object envelope (page, results, additionalProperties: true). Extra pagination fields from the live API (prev_page, total_results, etc.) are allowed via additionalProperties and do not need to be listed explicitly. The envelope uses OpenAPI 3.0 syntax only (no JSON Schema union types such as type: ["integer", "null"], which FastMCP's spec parser rejects).

OpenAPI patch files

If the upstream spec is incomplete or needs local corrections, you can layer one or more patch files on top of the downloaded spec before FastMCP ingests it:

openapi:
  spec: https://app.caflou.com/api/v1/i/docs/openapi/v1/openapi.yaml
  patch_files:
    - examples/caflou.accounts.patch.yaml

Patch files are parsed as YAML/JSON objects and deep-merged into the OpenAPI document. Mappings are merged recursively; lists are replaced in full. This keeps the server spec-driven even when the upstream file is re-downloaded periodically. Relative patch paths are resolved against the directory of the primary config file (the first file in MCP_HOOKER_CONFIG_FILES, or config.yaml by default).

In Docker, mount patch files into that same directory inside the container. If config.yaml is mounted at /app/config.yaml, then patch.yaml must also be available at /app/patch.yaml:

volumes:
  - ./config.yaml:/app/config.yaml:ro
  - ./patch.yaml:/app/patch.yaml:ro

Example Caflou patch for the missing GET /api/v1/accounts endpoint:

paths:
  /api/v1/accounts:
    get:
      tags:
        - Accounts
      operationId: List_Accounts
      summary: List accounts
      responses:
        "200":
          description: Accounts visible to the current token.
          content:
            application/json:
              schema:
                type: object
                properties:
                  result:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                required:
                  - result
                x-fastmcp-wrap-result: true

The repository includes that example as examples/caflou.accounts.patch.yaml. After reload, FastMCP should expose a generated List_Accounts MCP tool if the upstream API accepts the request.

Set the value via the environment (never commit it). With Docker Compose, copy .env.example to .env and fill in CAFLOU_API_TOKEN; the token is passed into the container and injected on every upstream call. See docs/RUNBOOK.md §4 (auth) and §6 (production deployment).

HTTP endpoints

Endpoint

Method

Purpose

/health

GET

Liveness + current spec/base URL

/admin/reload

POST

Re-read config and OpenAPI spec

/mcp

*

Streamable HTTP MCP (FastMCP default)

Reloading

  • HTTP: curl -X POST http://localhost:8000/admin/reload

  • Signal: kill -HUP <pid> when reload.on_sighup is true

  • Interval: set reload.interval_seconds to poll remote specs

Each reload closes the previous httpx client, re-parses config via yayaya, fetches the spec, and rebuilds the FastMCP OpenAPI provider.

Docker

docker build -t mcp-hooker .
docker run --rm -p 8000:8000 -v "$PWD/config.yaml:/app/config.yaml:ro" mcp-hooker

Or with Compose:

docker compose up --build

GitLab CI/CD

.gitlab-ci.yml mirrors zpl-mcp: build on a tagged runner, push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA, and tag latest on the default branch.

Register a runner with tag mcp-hooker (or change the tag in .gitlab-ci.yml to match your fleet).

Cursor / MCP client

Point your client at the streamable HTTP URL, for example:

{
  "mcpServers": {
    "my-api": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

Development

pip install -e ".[dev]"
ruff check mcp_hooker

Operations

See docs/RUNBOOK.md for architecture, deployment notes, and troubleshooting.

Voicebot ↔ Caflou (ElevenLabs): docs/voicebot-caflou-mcp.md — patch limits, filtered caflou-voice instance, thin MCP via voicebot-core. Sync Caflou project 615009: scripts/caflou_sync_voicebot_project.py.

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    D
    maintenance
    An MCP server that dynamically converts any OpenAPI or REST API into MCP tools, allowing for real-time server switching and schema reloading. It supports variable substitution for headers and bodies, enabling seamless authentication and interaction with multiple API environments.
    Last updated
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    Dynamically converts any OpenAPI v3 specification into a fully-functional Model Context Protocol (MCP) server.
    Last updated
    7
    Mozilla Public 2.0
  • F
    license
    -
    quality
    D
    maintenance
    MCP server that wraps any REST API with an OpenAPI spec, dynamically creating MCP tools at runtime without code generation.
    Last updated
    1

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/KodzghlyCZ/mcp-hooker'

If you have feedback or need assistance with the MCP directory API, please join our Discord server