Skip to content

Repository files navigation

What MCPTap does

MCPTap can:

  • Route traffic to OpenRouter or Requesty
  • Force all requests to use a configured model
  • Use a different model for plan mode
  • Pin or restrict OpenRouter provider routing
  • Intercept selected MCP tool calls
  • Execute real MCP tools locally through stdio
  • Log upstream requests and responses
  • Run a configurable hook before client tool calls to allow or block them
  • Rewrite tool call arguments via the hook (e.g. wrap shell commands with RTK for token compression)
  • Serve simple UI interface for debugging requests
  • Expose a local health endpoint

High-level flow

AI client
  │
  │ OpenAI-compatible request
  ▼
MCPTap
  │  rewrites payload: forced model, plan-mode switching,
  │  provider pinning, per-model instructions, tool injection
  │
  │  rewritten / routed request
  ▼
OpenRouter or Requesty
  │
  │  model response
  ▼
MCPTap
  │
  ├─ model calls an intercepted MCP tool:
  │      MCPTap calls the MCP server locally, feeds the tool
  │      result back to the model, and loops to the upstream again
  │
  ├─ model calls a client tool and the tool-call hook is enabled:
  │      MCPTap runs the hook script —
  │        allow: returns the saved model response to the client
  │        block: feeds the block message back to the model,
  │               then passes through the next response once
  │
  └─ final response (no intercepted or client tool calls pending)
       ▼
     AI client

Main use cases

MCPTap is designed for workflows like:

  • using Codex/Hermes Agent CLI through OpenRouter or Requesty,
  • forcing a cheaper model for normal work and a stronger model for planning,
  • giving a weaker model access to a stronger “expert” model through an MCP tool,
  • disabling access to sensitive files,
  • hiding complex MCP orchestration from the client,
  • debugging model/tool traffic,
  • testing provider fallback behavior,
  • controlling OpenRouter provider selection.

Installation

Install the latest release:

curl -fsSL https://github.com/PCODE-pl/MCPTap/releases/latest/download/setup.sh | sh

If curl is not available:

wget -qO- https://github.com/PCODE-pl/MCPTap/releases/latest/download/setup.sh | sh

The installer creates a local Python virtual environment, installs MCPTap files, copies example configuration files, and tries to install a user service.

Default paths:

~/.local/share/mcptap       application files and logs database
~/.local/bin/mcptap         executable wrapper
~/.config/mcptap            configuration files

File access blocking (optional, Linux only)

To build and install the LD_PRELOAD file-block library during installation, pass --with-file-block:

sh setup.sh --with-file-block

Or when piping from curl/wget:

curl -fsSL https://github.com/PCODE-pl/MCPTap/releases/latest/download/setup.sh | sh -s -- --with-file-block

This option is Linux-only. It requires a C compiler (gcc or cc), make, and C library headers (libc-dev/glibc-devel). The installer checks for these tools and reports installation instructions if any are missing.

When --with-file-block is used on a new installation (where proxy.env does not already exist), the installer:

  1. Builds libmcptap_fileblock.so from the file_block/ source directory.
  2. Installs it to ~/.local/lib/libmcptap_fileblock.so.

On subsequent runs with --with-file-block, the library is rebuilt and reinstalled, but proxy.env is left untouched (to preserve user edits). Use --force-config to reset proxy.env to defaults and re-wire the library path.

On macOS, --with-file-block is silently skipped (the file-block library is not yet supported on macOS).

After installation, start Codex with the library loaded:

LD_PRELOAD=~/.local/lib/libmcptap_fileblock.so codex

Hermes Agent can be started in the same way:

LD_PRELOAD=~/.local/lib/libmcptap_fileblock.so hermes

See the Tool-call hook section for details on how blocked_files from the hook are enforced by this library.

Configuration files

After installation, edit the files in:

~/.config/mcptap/

Important files:

proxy.env          main MCPTap configuration
openrouter.env     OpenRouter model and API key configuration
requesty.env       Requesty model and API key configuration
mcp-intercept.yaml optional MCP tool interception configuration
per-model.yaml     optional per-model instruction overrides
use_tool_hook.py   optional tool-call hook script (runs before client tool calls)

Quick start

1. Select the upstream provider

Edit:

~/.config/mcptap/proxy.env

Example for OpenRouter:

MCP_TAP_UPSTREAM_PROVIDER=openrouter
MCP_TAP_LISTEN_HOST=127.0.0.1
MCP_TAP_LISTEN_PORT=8787

Example for Requesty:

MCP_TAP_UPSTREAM_PROVIDER=requesty
MCP_TAP_LISTEN_HOST=127.0.0.1
MCP_TAP_LISTEN_PORT=8787

Supported upstream providers:

openrouter
requesty

2. Configure the provider

For OpenRouter, edit:

~/.config/mcptap/openrouter.env

Example:

MCP_TAP_API_KEY=sk-or-v1-...
MCP_TAP_MODEL=deepseek/deepseek-v4-flash:floor
MCP_TAP_PLAN_MODE_MODEL=z-ai/glm-5.2:floor

For Requesty, edit:

~/.config/mcptap/requesty.env

Example:

MCP_TAP_API_KEY=rqsty-sk-...
MCP_TAP_MODEL=nvidia/nemotron-3-nano-30b-a3b:free
MCP_TAP_PLAN_MODE_MODEL=zai/glm-5.2:floor

Codex configuration

Example Codex configuration:

model_provider = "mcptap"
model = "openai/gpt-5.5"
model_context_window = 1000000

# This value must be different from MCP_TAP_PLAN_MODE_TRIGGER.
# For this reasoning effort, MCPTap will use MCP_TAP_MODEL
# from the selected provider env file.
model_reasoning_effort = "xhigh"

# This value must match MCP_TAP_PLAN_MODE_TRIGGER.
# For this reasoning effort, MCPTap will use MCP_TAP_PLAN_MODE_MODEL
# from the selected provider env file.
plan_mode_reasoning_effort = "max"

model_supports_reasoning_summaries = false
web_search = "live"

[model_providers.mcptap]
name = "routed-via-mcptap"
base_url = "http://127.0.0.1:8787/v1"
wire_api = "responses"
http_headers = { "X-Title" = "OpenAI Codex" }
supports_websockets = false

[memories]
extract_model = "openai/gpt-5.5"
consolidation_model = "openai/gpt-5.5"

Hermes Agent configuration

Example Hermes Agent configuration:

model:
  [...]
  provider: custom
  base_url: http://127.0.0.1:8787/v1
  api_mode: codex_responses

Features

Service management

Linux

Start:

systemctl --user start mcptap.service

Restart:

systemctl --user restart mcptap.service

Stop:

systemctl --user stop mcptap.service

Status:

systemctl --user status mcptap.service

Logs:

journalctl --user -u mcptap.service -f

macOS

MCPTap is installed as a launchd user service:

pl.pcode.mcptap

Restart:

launchctl kickstart -k "gui/$(id -u)/pl.pcode.mcptap"

Logs:

tail -f ~/Library/Logs/mcptap.log ~/Library/Logs/mcptap.error.log

Manual start

If the service is not installed, run MCPTap manually:

mcptap

or:

~/.local/bin/mcptap

Health endpoint

Check it with:

curl http://127.0.0.1:8787/health

Troubleshooting

See docs/TROUBLESHOOTING.md for common issues and their solutions.

Security notes

If MCP_TAP_LOG_FILE is enabled, consider:

LOG_FILE_REDACT_HEADERS=1

MCP tools are executed locally with the permissions of the MCPTap process.

Development

See docs/DEVELOPMENT.md for development setup, running locally, and linting configuration.

Issues

The list of issues that MCPTap addresses (at least partially): docs/ISSUES.md.

Configuration reference

proxy.env

Variable Default Value Description
MCP_TAP_UPSTREAM_PROVIDER required openrouter or requesty.
MCP_TAP_LISTEN_HOST 127.0.0.1 Local host/interface to bind.
MCP_TAP_LISTEN_PORT 8787 Local port to listen on.
MCP_TAP_OPENROUTER_PROVIDER empty Optional OpenRouter provider slug.
MCP_TAP_OPENROUTER_DISABLE_PROVIDER_FALLBACKS 1 Disable OpenRouter provider fallback when true.
MCP_TAP_PLAN_MODE_TRIGGER max Reasoning effort value that activates plan mode model.
MCP_TAP_PLAN_MODE_MAX_INPUT_SIZE 300000 Maximum accepted input size for plan mode.
MCP_TAP_INTERCEPT_YAML empty MCP interception YAML or @/path/to/file.yaml.
MCP_TAP_INTERCEPT_MAX_ITERATIONS 8 Maximum hidden tool-call loop iterations.
MCP_TAP_INTERCEPT_TOOL_TIMEOUT 120 Timeout for one MCP tool call, in seconds.
MCP_TAP_PER_MODEL_YAML empty Per-model instruction YAML or @/path/to/file.yaml.
MCP_TAP_USE_TOOL_HOOK empty Path to a Python hook script run before client tool calls.
MCP_TAP_USE_TOOL_HOOK_TIMEOUT 30 Timeout for the hook script, in seconds.
MCP_TAP_USE_TOOL_HOOK_SYNTHETIC_TOOL get_goal Synthetic tool name to inject before the hook. Empty = direct mode.
MCP_TAP_PER_SESSION_DIR /tmp/mcptap/per_session Directory for per-session control files.
MCP_TAP_LOG_LEVEL INFO Python logging level.
MCP_TAP_LOG_FILE empty Optional communication log file path.
LOG_FILE_REDACT_HEADERS 0 Redact sensitive headers in communication logs when true.

openrouter.env and requesty.env

Variable Required Description
MCP_TAP_API_KEY yes Upstream provider API key.
MCP_TAP_MODEL yes Default forced model.
MCP_TAP_PLAN_MODE_MODEL yes Forced model used when plan mode is active.

LD_PRELOAD file-block library

Variable Default Value Description
MCPTAP_FB_DIR /tmp/mcptap/per_session Directory for per-session control files.
MCPTAP_FB_INTERPRETERS see file_block.c Colon-separated list of basenames treated as interpreters.
MCPTAP_FB_ESCALATORS see file_block.c Colon-separated list of argv[0] basenames treated as privilege-escalators.
MCPTAP_FB_DISABLE_ESCALATOR_CHECK unset When set to 1, the surgical escalator+interpreter layer is disabled entirely (only the path-scan layer remains active).

About

MCPTap is a lightweight LLM proxy for AI agents that intercepts traffic (currently OpenRouter/Requesty) and controls MCP tool calls / protects files from AI agent.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages