Upstream: https://github.com/BANCS-Norway/tmux-mcp
MCP server that bridges Claude Chat ↔ Claude Code by driving a tmux session
on the host machine. Authenticates users via GitHub OAuth; the MCP server
itself is a full OAuth 2.1 authorization server (with Dynamic Client
Registration), so it works as a remote connector in the Claude mobile app.
| Command | What it does |
|---|---|
tmux-mcp |
Run the MCP server (the OAuth + tool host) |
tmux-mcp-enricher |
Watch logs/pending/, enrich + move files to logs/staged/ |
tmux-mcp-report |
Submit staged abuse reports from the shell (--list, --all, or a filename) |
tmux-mcp-report supports tab-completion of staged filenames. The CLI prints the right snippet for your shell — pipe it into your rc file:
# auto-detect from $SHELL
echo "$(tmux-mcp-report --register)" >> ~/.zshrc
# or pick the shell explicitly
tmux-mcp-report --register bash >> ~/.bashrc
tmux-mcp-report --register zsh >> ~/.zshrc| Tool | What it does |
|---|---|
tmux_list_sessions |
List active tmux sessions on the host |
tmux_get_summary |
Capture the last N lines from a tmux pane |
tmux_send_prompt |
Send a prompt string to a tmux pane (optional Enter) |
abuse_get_pending |
List IPs still accumulating 429 responses in pending/ |
abuse_get_staged |
List enriched abuse reports in staged/ (ready to submit) |
abuse_list_reported |
List archived submissions in reported/ (period required) |
abuse_send_report |
Submit an abuse report to AbuseIPDB and archive the file |
The abuse_* tools pair with the optional abuse reporting pipeline below. abuse_send_report requires TMUX_MCP_ABUSEIPDB_KEY; the others work with just the log directory.
tmux-mcp is built and run with uv. Install it via astral's instructions, e.g.:
curl -LsSf https://astral.sh/uv/install.sh | shOnce you have uv on $PATH you can pick either install style below.
Claude remote connectors require https://. The easiest path is
Tailscale Serve:
sudo tailscale serve --bg --https=443 http://localhost:8747Your public URL becomes https://<machine>.<tailnet>.ts.net. This is also
tailnet-scoped — only devices signed into your tailnet can reach it.
At https://github.com/settings/developers → New OAuth App:
- Homepage URL:
https://<machine>.<tailnet>.ts.net - Authorization callback URL:
https://<machine>.<tailnet>.ts.net/oauth/github/callback
Generate a client secret and save both values.
Copy the example and fill in the values:
cp .env.example .env
$EDITOR .envRequired:
| Env var | Purpose |
|---|---|
TMUX_MCP_PUBLIC_URL |
HTTPS URL from step 1 (no trailing slash) |
TMUX_MCP_GITHUB_CLIENT_ID |
GitHub OAuth app client ID |
TMUX_MCP_GITHUB_CLIENT_SECRET |
GitHub OAuth app client secret |
TMUX_MCP_ALLOWED_GITHUB_USERS |
Comma-separated GH usernames permitted to log in |
Optional:
| Env var | Default | Purpose |
|---|---|---|
TMUX_MCP_PORT |
8747 |
Backend HTTP port |
TMUX_MCP_HOST |
0.0.0.0 |
Bind host. 127.0.0.1 when fronting with tailscale serve. TAILSCALE auto-binds to Tailscale IP. |
TMUX_MCP_SESSION |
0 |
Default tmux session target for tools |
Two install styles — pick one:
Style A — global tool (commands on $PATH)
Install directly from the repo URL:
uv tool install git+https://github.com/BANCS-Norway/tmux-mcp
tmux-mcp…or from a local clone (handy if you've already cloned for .env.example etc.):
git clone https://github.com/BANCS-Norway/tmux-mcp
cd tmux-mcp
uv tool install .
tmux-mcpEither form installs tmux-mcp, tmux-mcp-enricher, and tmux-mcp-report into ~/.local/bin (or wherever uv tool install puts them). After that you can drop the uv run prefix everywhere — the Commands table at the top of this README assumes this style.
To upgrade later: uv tool upgrade tmux-mcp.
Style B — development clone (uses uv run)
git clone https://github.com/BANCS-Norway/tmux-mcp
cd tmux-mcp
uv sync
uv run tmux-mcpBest when you're hacking on the code. Every snippet in this README that says tmux-mcp-... becomes uv run tmux-mcp-... from inside the repo.
In Claude (desktop or mobile) → Settings → Connectors → Add custom connector:
- URL:
https://<machine>.<tailnet>.ts.net/mcp
Claude will discover the OAuth endpoints, you'll be sent through GitHub login,
and if your username is in TMUX_MCP_ALLOWED_GITHUB_USERS the connector
activates.
- Claude hits
/.well-known/oauth-authorization-serverfor discovery. - Claude registers itself via Dynamic Client Registration (
/register). Registered clients persist in~/.config/tmux-mcp/clients.json. - Claude opens
/authorize— the server redirects to GitHub. - GitHub redirects back to
/oauth/github/callbackwith a code. - The server exchanges the code for a GitHub access token, fetches the
username, and checks it against
TMUX_MCP_ALLOWED_GITHUB_USERS. - The server issues an RS256 JWT (signed with a key auto-generated at
~/.config/tmux-mcp/jwt-key.pem) and redirects back to Claude. - Every MCP request carries the JWT as a bearer token. The server verifies the signature and expiry before dispatching tools.
Access tokens live for 1 hour. There are no refresh tokens in v1 — clients just re-auth, which is quick since GitHub remembers the authorization.
~/.config/tmux-mcp/
├── clients.json # DCR-registered clients (mode 600)
└── jwt-key.pem # RSA private key for signing access tokens (mode 600)
A three-part pipeline for collecting malicious IP activity and submitting reports to AbuseIPDB:
-
Collector — the rate-limit middleware writes every 429 to
{TMUX_MCP_LOG_DIR:-./logs}/pending/{ip}.log(built into the server, always on). -
Enricher — a separate process watches
pending/, debounces (60s quiet window), looks up ASN + country via RIPE Stat, detects AbuseIPDB categories, and moves files tostaged/. Run alongside the server:tmux-mcp-enricher
Runs independently — restart either without affecting the other. RIPE lookup failures are non-fatal; enrichment proceeds with
unknownfields. -
MCP tools —
abuse_get_pending,abuse_get_staged,abuse_list_reported,abuse_send_report. Use them from the agent to inspect the pipeline and submit reports.
abuse_send_report requires a free AbuseIPDB account:
-
Sign up at abuseipdb.com/register.
-
Verify your email.
-
Go to abuseipdb.com/account/api and click Create Key. The free tier allows up to 1,000 submissions per day — plenty for a single-host deployment.
-
Add the key to
.env:TMUX_MCP_ABUSEIPDB_KEY=your-key-here
-
Restart the server (
tmux-mcp) so it picks up the new env var.
Without the key, abuse_send_report returns a clear error instead of attempting the call — the collector and enricher run fine without it, so you can start gathering data before deciding whether to submit.
Optional shell helpers that pair well with tmux-mcp — e.g. repo-tmux for auto-attaching to a per-repo tmux session when you open a terminal. See tools/shells/.
uv run ruff check
uv run ruff formatMIT