Skip to main content

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.

Metadata

Release files for shack-gateway 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for shack-gateway 0.1.0
File Size Uploaded Provenance
shack_gateway-0.1.0.tar.gz 29.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for shack-gateway 0.1.0
File Interpreter ABI Platform
shack_gateway-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.3 kB

Release files / shack_gateway-0.1.0.tar.gz

Download URL shack_gateway-0.1.0.tar.gz
Size 29.0 kB
Tags Source
SHA-256 checksum
How to use checksums
63a759948aa1768081dd5c303f384405fd55ada49ccdf1970f4e0610945890bf
BLAKE2b-256 checksum
How to use checksums
ba80f88e737cc161bca96ce066ab7bd438f0fc6ff7a6ecc8a8e20942813bede8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Release files / shack_gateway-0.1.0-py3-none-any.whl

Download URL shack_gateway-0.1.0-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cdc8b0cdaf2e33a2fb3983bba86b94d57e00c9792e5466b9afaad771c25b5e62
BLAKE2b-256 checksum
How to use checksums
e699c47c7a1aefaf181f49f1f30797ed5fe88e185f3953720866ea21448b8a31
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Security for shack-gateway 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page