Tailnet MCP Server
by AlexSKorn
README.md
# Tailnet MCP Server
**Why I built this:** I built this to learn Tailscale - this was my first time using it. From past experience debugging network issues, I thought having an MCP to feed network state directly into an LLM could make diagnosing connectivity problems much easier than context-switching between CLI output and chat windows.
---
A Model Context Protocol (MCP) server that exposes your Tailscale tailnet as a queryable resource for LLMs. Query devices, check connectivity, and get network status directly from your AI assistant.
## Prerequisites
- Docker
- A [Tailscale](https://tailscale.com/) account with at least one device on your tailnet
## Setup & Test
1. **Clone & enter the repo:**
```bash
git clone https://github.com/AlexSKorn/TailscaleMCP.git
cd TailscaleMCP
```
2. **Get an Auth Key:** Go to your [Tailscale Admin Console](https://login.tailscale.com/admin/settings/keys), click "Generate auth key", and copy the key (starts with `tskey-auth-`).
3. **Configure & start:**
```bash
make setup # creates .env from template
# edit .env and paste your TS_AUTHKEY
make docker-up # start containers
make docker-test # should print "Connection test: OK"
```
4. **Try it interactively** with the MCP Inspector:
```bash
npx @modelcontextprotocol/inspector docker compose exec -T tailnet-mcp python -m tailnet_mcp.server
```
Open the URL shown in your terminal (usually `http://localhost:3000`), click **Connect** and then **"List Tools"**, then pick any tool and click **"Run"**.
### Available Tools
| Tool | Input | What it does |
|------|-------|-------------|
| `list_devices` | `{}` or `{"online_only": true}` | List all devices on your tailnet |
| `get_device` | `{"hostname": "your-device"}` | Detailed info for a specific device |
| `get_tailnet_status` | `{}` | Network overview (MagicDNS, version, device count) |
| `check_connectivity` | `{"hostname": "your-device"}` | Ping a device and report latency |
| `list_exit_nodes` | `{}` | List available exit nodes |
### Cleanup
```bash
make docker-down # stop containers (keeps state)
make docker-clean # stop and remove all data
```
---
## Architecture
```
MCP Client (stdio) ←→ tailnet-mcp (FastMCP) ←→ tailscale (Unix socket)
↓
/localapi/v0/*
```
1. MCP client sends tool calls via stdio
2. Server translates them to Tailscale Local API requests over a Unix socket
3. Tailscale daemon responds with network state
4. Server formats responses for human readability
**Key design decisions:**
- **Read-only** — the server cannot modify Tailscale settings, add/remove devices, or change ACLs
- **Local API only** — all calls stay on the local machine (no external network calls, no stored credentials)
- **Async throughout** — httpx for socket I/O, subprocess for pings
## Project Structure
```
src/tailnet_mcp/
├── server.py # MCP server & tool definitions
├── tailscale.py # Tailscale local API client (async httpx over Unix socket)
├── models.py # Pydantic data models
tests/
└── test_server.py # pytest + pytest-asyncio tests
```
## Development
```bash
pip install -e ".[dev]" # install with dev dependencies
make test # run tests
make check-all # lint + format + type-check + tests
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues