Skip to main content

Progressive-discovery, security-hardened MCP gateway and aggregator

Project description

shack-gateway (Python)

An aggregating MCP server that multiplexes multiple downstream MCP servers behind a single, security-hardened gateway. Speaks JSON-RPC 2.0 over stdio; STDOUT carries only protocol messages and all log output goes to STDERR.

What it does

  • Connects to one or more downstream MCP servers at startup and aggregates their tools and resources into a unified namespace (server__tool).
  • Exposes a progressive-discovery surface by default: four shack_* meta-tools let clients explore and invoke downstream tools without loading every schema at once. In full mode every downstream tool is exposed directly.
  • Runs every tool call through a security pipeline: workspace sandbox (path containment), declarative allow/deny permission rules, and optional pre/post shell hooks.
  • Redacts sensitive field names (tokens, secrets, keys, etc.) from log output automatically.

MCP tools

Tool Arguments Description
shack_list_tools query? (string), server? (string) List downstream tools as compact {name, server, summary} entries. Filter by server name or a case-insensitive keyword. Returns no input schemas — use shack_describe_tool for a full schema.
shack_describe_tool name (string, required) Return the full description and JSON input schema for one namespaced tool (server__tool).
shack_call_tool name (string, required), arguments? (object) Invoke a downstream tool by namespaced name. Passes through the full sandbox, permission, and hook pipeline before routing.
shack_list_servers List connected downstream servers with their tool counts.

In expose_mode: progressive (the default) only the four meta-tools above appear in tools/list. In expose_mode: full every downstream tool is listed directly.

Configuration

The gateway reads a JSON file (default shack-config.json). All fields except workspace_root are optional.

Field Type Default Description
workspace_root string required Absolute path; tool arguments containing paths are checked to stay inside this directory.
expose_mode "progressive" or "full" "progressive" Controls how downstream tools are surfaced.
servers object {} Map of server name to {command, args?, env?} objects.
permissions.default_decision "allow" / "deny" / "prompt" "allow" Fallback when no allow/deny rule matches.
permissions.allow string[] [] Patterns that explicitly allow calls, e.g. fs__read(*).
permissions.deny string[] [] Patterns that explicitly block calls. Evaluated before allow.
pre_tool_hook string none Shell command run before every tool call; may modify arguments or deny.
post_tool_hook string none Shell command run after every tool call; may reject results.
redact_fields string[] built-in list JSON field names whose values are masked in logs.
request_timeout_secs integer 30 Per-request timeout applied to downstream calls.

Permission rule syntax

Rules have the form tool_name(subject_pattern):

  • fs__write(*) — match any call to fs__write.
  • bash(rm -rf:*) — match calls where the subject starts with rm -rf.
  • git(checkout) — exact match on the subject value checkout.

The subject is extracted from the first matching well-known argument key: command, path, file_path, url, query, etc.

Minimal config example:

{
  "workspace_root": "/home/user/project",
  "expose_mode": "progressive",
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/project"]
    }
  }
}

Install

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

Run

shack-gateway --config shack-config.json

The server reads newline-delimited JSON-RPC 2.0 from stdin and writes responses to stdout. Log output goes to stderr.

CLI flags

Flag Default Description
--config / -c shack-config.json Path to the gateway JSON configuration file.

Usage example

The following shows a complete JSON-RPC 2.0 interaction over stdio. Each request is one line; each response is one line.

Request — list available tools:

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"shack_list_tools","arguments":{}}}

Response — compact tool list (empty with no configured downstream servers):

{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"tools\":[],\"count\":0}"}]}}

Request — call a downstream tool by namespaced name:

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"shack_call_tool","arguments":{"name":"filesystem__read_file","arguments":{"path":"src/main.py"}}}}

Test

pip install pytest
pytest

Unit tests cover config parsing, tool catalog registration and search, permission rule evaluation, sandbox path validation, redaction, and hook invocation. Integration tests in tests/test_proxy.py spawn the gateway process over stdio and exercise the full JSON-RPC surface.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shack_gateway-0.1.0.tar.gz (29.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shack_gateway-0.1.0-py3-none-any.whl (24.3 kB view details)

Uploaded Python 3

File details

Details for the file shack_gateway-0.1.0.tar.gz.

File metadata

  • Download URL: shack_gateway-0.1.0.tar.gz
  • Upload date:
  • Size: 29.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for shack_gateway-0.1.0.tar.gz
Algorithm Hash digest
SHA256 63a759948aa1768081dd5c303f384405fd55ada49ccdf1970f4e0610945890bf
MD5 4d53ef87a0ca72a8eef4473b67017d7c
BLAKE2b-256 ba80f88e737cc161bca96ce066ab7bd438f0fc6ff7a6ecc8a8e20942813bede8

See more details on using hashes here.

File details

Details for the file shack_gateway-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: shack_gateway-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 24.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for shack_gateway-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cdc8b0cdaf2e33a2fb3983bba86b94d57e00c9792e5466b9afaad771c25b5e62
MD5 b35a97379ee6b816305cc13b10de4c76
BLAKE2b-256 e699c47c7a1aefaf181f49f1f30797ed5fe88e185f3953720866ea21448b8a31

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page