Skip to main content
Glama

mcp-prov

Local MCP proxy in Python that wraps an existing MCP server in n8n (Metrotel's provisioning instance). It adds caching, logging, composite diagnostic tool, and its own Bearer auth without touching the backend.

Image on Docker Hub: metrotel/mcp-prov

  • 🌐 Speaks stdio (Claude Code / embedded clients) or HTTP (Claude Desktop and others)

  • πŸ” Isolates the upstream token: never exposed to the client

  • ⚑ 60s in-memory cache for idempotent reads (config via env var)

  • πŸ“ JSON-lines log of each tool call (tool, args, cached, duration_ms, error)

  • πŸ›  Exposes the 32 upstream tools + a composite tool diagnostico_completo

  • ♻️ Re-initializes the session if the upstream closes it (known n8n MCP bug)

  • πŸš€ Deploy: Docker / Docker Swarm / Kubernetes / systemd user unit / standalone Python

  • πŸ’Ύ /data volume for persistent logs (and future cache)

Why it exists

The MCP server embedded in Metrotel's n8n flow closes the SSE long-poll after a period of inactivity, and clients like mcp-remote start making noisy retries. Also, the upstream token lived in plaintext config JSONs.

This proxy:

  • Eliminates the long-poll: each tool call opens its own HTTP request to the upstream and closes when done.

  • Isolates the upstream token (X-Prov-MCP-Key): it lives only in the proxy's env file, not in Claude Desktop / Claude Code configs.

  • Adds caching for repeated reads (e.g., the same contexto_servicio several times within a few minutes).

  • Adds a composite tool that chains several upstream tools and returns a summary β€” avoids the model having to orchestrate 3 calls when it can ask for a single one.

Related MCP server: @qelos/better-mcp

Requirements

  • Python 3.10+

  • uv (recommended, or pip)

  • Network access to the upstream MCP server and a valid X-Prov-MCP-Key header

Quickstart

docker run -d --name prov-mcp -p 8767:8767 \
  -e PROV_MCP_KEY='pmcc_...' \
  -e PROV_MCP_AUTH_TOKEN='pmcp_...' \
  -v prov-data:/data \
  --restart unless-stopped \
  metrotel/mcp-prov:0.2.2

Or with the repo's docker-compose.yml:

git clone https://github.com/datacenter-metrotel/mcp-prov.git
cd mcp-prov
cp .env.example .env && chmod 600 .env    # editΓ‘ .env
docker compose up -d

Log persisted in the prov-data volume (mounted to /data/logs):

docker exec prov-mcp tail -f /data/logs/calls.log

Native HTTP mode (without Docker)

git clone https://github.com/datacenter-metrotel/mcp-prov.git
cd mcp-prov

cp .env.example .env
chmod 600 .env
# editΓ‘ .env con los valores reales

# Arrancar en foreground
uvx --from . prov-mcp-proxy
# server escuchando en http://0.0.0.0:8767/mcp

Verify:

KEY=$(grep '^PROV_MCP_AUTH_TOKEN=' .env | cut -d= -f2)
curl -sS -L -X POST http://127.0.0.1:8767/mcp \
  -H "Authorization: Bearer $KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}'

stdio mode (for Claude Code / Cursor or other clients that start the process)

export PROV_MCP_KEY='pmcc_...'
export PROV_MCP_TRANSPORT=stdio
uvx --from . prov-mcp-proxy

And in .mcp.json (Claude Code):

{
  "mcpServers": {
    "prov": {
      "command": "uvx",
      "args": ["--from", "/ruta/al/repo", "prov-mcp-proxy"],
      "env": { "PROV_MCP_KEY": "${PROV_MCP_KEY}" }
    }
  }
}

Deploy on Kubernetes / Docker Swarm

  • Kubernetes with envFrom.secretRef + PersistentVolumeClaim: see k8s/README.md.

  • Docker Swarm with secrets encrypted in raft + volume: see swarm/README.md.

Deploy as a systemd user unit

Template in systemd/prov-mcp-proxy.service.example:

mkdir -p ~/.config/systemd/user ~/.config/prov-mcp-proxy
cp systemd/prov-mcp-proxy.service.example ~/.config/systemd/user/prov-mcp-proxy.service
cp .env.example ~/.config/prov-mcp-proxy/env
chmod 600 ~/.config/prov-mcp-proxy/env
# editΓ‘ ~/.config/prov-mcp-proxy/env con los valores reales

systemctl --user daemon-reload
systemctl --user enable --now prov-mcp-proxy.service
systemctl --user status prov-mcp-proxy.service

To survive reboots without login: sudo loginctl enable-linger $USER.

Usage from Claude Desktop

Edit claude_desktop_config.json:

{
  "mcpServers": {
    "prov": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "http://<HOST_IP>:8767/mcp",
        "--allow-http",
        "--transport", "http-only",
        "--header", "Authorization:Bearer <PROV_MCP_AUTH_TOKEN>"
      ]
    }
  }
}

Config paths:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux (community): ~/.config/Claude/claude_desktop_config.json

See the full example in examples/claude_desktop_config.example.json.

Environment variables

Variable

Required

Default

Description

PROV_MCP_KEY

βœ…

β€”

X-Prov-MCP-Key header sent to the upstream

PROV_MCP_AUTH_TOKEN

βœ… (if TRANSPORT=http)

β€”

Bearer that MCP clients must send in Authorization

PROV_MCP_URL

❌

https://n8n-asegured.metrotel.com.ar/mcp/prov_mcp_cc

Upstream endpoint

PROV_MCP_TRANSPORT

❌

stdio

stdio or http

PROV_MCP_HTTP_HOST

❌

127.0.0.1

HTTP listener bind

PROV_MCP_HTTP_PORT

❌

8767

Port

PROV_MCP_HTTP_PATH

❌

/mcp

Endpoint path

PROV_MCP_CACHE_TTL

❌

60

Cache TTL in seconds (0 = off)

PROV_MCP_LOG_DIR

❌

~/.cache/prov_mcp_proxy

JSON-lines log directory

Exposed tools

All upstream tools are re-exposed as-is (32 at the time of writing), plus a composite one:

  • diagnostico_completo(service_number) β€” calls contexto_servicio β†’ Topologia β†’ (if the subproduct is ISI) ISI_Check_IP, and returns a grouped summary. Useful as an "entry point" for quick diagnosis of a service given its number.

See the details of the upstream tools in the Postman collection in postman/.

Cache

Tools that are never cached (active effects or volatile data):

  • Ping_tool

  • ATA_Test_1, ATA_Test_2, ATA_Test_3

  • Gestion_ACS

  • Obtener_backup_equipo

The rest go into the cache with a configurable TTL (default 60s). The key includes tool name + SHA1 hash of the normalized arguments.

Log

Each tool call is recorded in ~/.cache/prov_mcp_proxy/calls.log as a JSON line with ts, tool, args, cached, duration_ms, error. Automatic rotation 5 MB Γ— 3.

Security

See SECURITY.md. In summary:

  • Bearer required in HTTP mode (Starlette middleware).

  • Upstream token never leaves the proxy.

  • Env file with credentials goes with chmod 600, outside git.

  • .env in .gitignore.

License

MIT β€” see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Local-first MCP proxy with BM25 tool discovery, quarantine security, Docker isolation, OAuth support, activity logging, and web UI. Routes multiple upstream MCP servers through a single endpoint.
    9
    334
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    A stdio MCP proxy that connects to one or more upstream MCP servers and exposes their tools, resources, and prompts through a single endpoint with a configurable middleware pipeline.
    14
    16
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A standalone MCP server that exposes Rancher-side tools, forwards Authorization headers or uses configured credentials, and supports HTTP and stdio transports.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Lifts local stdio MCP servers into remote Streamable HTTP endpoints for cloud-hosted AI clients, with bearer-token auth and tool policy filtering.
    15
    MIT

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/datacenter-metrotel/mcp-prov'

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