
Tailscale
STDIOMCP server for Tailscale network management and monitoring via CLI and API
MCP server for Tailscale network management and monitoring via CLI and API
A modern Model Context Protocol (MCP) server that provides seamless integration with Tailscale's CLI commands and REST API, enabling automated network management and monitoring through a standardized interface.
@hexsleeves/tailscale-mcp-server
hexsleeves/tailscale-mcp-server
ghcr.io/hexsleeves/tailscale-mcp-server
Run directly without installation:
# Method 1: Explicit package syntax (most reliable) npx --package=@hexsleeves/tailscale-mcp-server tailscale-mcp-server # Method 2: Direct syntax (may work depending on npx version) npx -y @hexsleeves/tailscale-mcp-server
Note: Method 1 with
--package=
syntax is more reliable across different npx versions and environments.
Or install globally:
npm install -g @hexsleeves/tailscale-mcp-server tailscale-mcp-server
# Pull and run from Docker Hub docker run -d \ --name tailscale-mcp \ -e TAILSCALE_API_KEY=your_api_key \ -e TAILSCALE_TAILNET=your_tailnet \ hexsleeves/tailscale-mcp-server:latest
# Pull and run from GitHub Container Registry docker run -d \ --name tailscale-mcp \ -e TAILSCALE_API_KEY=your_api_key \ -e TAILSCALE_TAILNET=your_tailnet \ ghcr.io/hexsleeves/tailscale-mcp-server:latest
# Use the included docker-compose.yml docker-compose up -d
Add to your Claude Desktop configuration (~/.claude/claude_desktop_config.json
):
{ "mcpServers": { "tailscale": { "command": "npx", "args": [ "--package=@hexsleeves/tailscale-mcp-server", "tailscale-mcp-server" ], "env": { "TAILSCALE_API_KEY": "your-api-key-here", "TAILSCALE_TAILNET": "your-tailnet-name" } } } }
{ "mcpServers": { "tailscale": { "command": "docker", "args": [ "run", "--rm", "-i", "-e", "TAILSCALE_API_KEY=xxxxxxxxxxxxx", "-e", "TAILSCALE_TAILNET=your-tailnet", "hexsleeves/tailscale-mcp-server:latest" ] } } }
{ "mcpServers": { "tailscale-docker": { "command": "docker", "args": [ "run", "--rm", "-i", "-e", "TAILSCALE_API_KEY=xxxxxxxxxxxxx", "-e", "TAILSCALE_TAILNET=your-tailnet", "ghcr.io/hexsleeves/tailscale-mcp-server:latest" ] } } }
# Required for API operations export TAILSCALE_API_KEY="your-api-key" export TAILSCALE_TAILNET="your-tailnet" # Optional: Custom API base URL export TAILSCALE_API_BASE_URL="https://api.tailscale.com" # Optional: Logging configuration export LOG_LEVEL="1" # 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR export MCP_SERVER_LOG_FILE="tailscale-mcp-{timestamp}.log" # Enable file logging
list_devices
- List all devices in the Tailscale networkdevice_action
- Perform actions on specific devices (authorize, deauthorize, delete, expire-key)manage_routes
- Enable or disable routes for devicesget_network_status
- Get current network status from Tailscale CLIconnect_network
- Connect to the Tailscale networkdisconnect_network
- Disconnect from the Tailscale networkping_peer
- Ping a peer deviceget_version
- Get Tailscale version informationget_tailnet_info
- Get detailed network informationFor local development and testing, clone the repository and set up the development environment:
# Clone the repository git clone https://github.com/HexSleeves/tailscale-mcp-server.git cd tailscale-mcp-server # Install dependencies npm install # Build the project npm run build
# Copy the example environment file cp .env.example .env # Create logs directory mkdir -p logs # Edit .env with your actual Tailscale credentials # TAILSCALE_API_KEY=your-actual-api-key # TAILSCALE_TAILNET=your-actual-tailnet
The .env.example
file contains all available configuration options with documentation. Key variables for testing:
0
for debug logging during developmentFor development, configure Claude Desktop to use your local build:
{ "mcpServers": { "tailscale-dev": { "command": "node", "args": ["/path/to/your/tailscale-mcp-server/dist/index.js"], "env": { "TAILSCALE_API_KEY": "your-api-key-here", "TAILSCALE_TAILNET": "your-tailnet-name", "LOG_LEVEL": "0" } } } }
{ "mcpServers": { "tailscale-dev": { "command": "npm", "args": ["run", "start"], "cwd": "/path/to/your/tailscale-mcp-server", "env": { "TAILSCALE_API_KEY": "your-api-key-here", "TAILSCALE_TAILNET": "your-tailnet-name", "LOG_LEVEL": "0" } } } }
# Build for development npm run build:dev # Build and watch for changes npm run build:watch # Run in development mode with auto-restart npm run dev # Run tests npm test # Run tests in watch mode npm run test:watch # Run tests with coverage npm run test:coverage # Test with MCP Inspector npm run inspector # Lint code npm run lint # Format code npm run format
The project includes an interactive publishing script that handles version bumping and publishing to multiple registries:
# Run the interactive publish script npm run publish # Or run directly ./scripts/publish.sh
The script will guide you through:
npm login
and proper access to the packagedocker login
docker login ghcr.io
using a GitHub tokenFor Docker-based development:
# Build development image docker build -t tailscale-mcp-dev . # Run with development environment docker run -it --rm \ -v $(pwd):/app \ -v /app/node_modules \ -e TAILSCALE_API_KEY=your_api_key \ -e TAILSCALE_TAILNET=your_tailnet \ -e LOG_LEVEL=0 \ tailscale-mcp-dev # Or use Docker Compose for development docker-compose -f docker-compose.dev.yml up
src/ ├── server.ts # Main server implementation ├── tools/ # Modular tool definitions │ ├── index.ts # Tool registry system │ ├── device-tools.ts # Device management tools │ └── ... # Additional tool modules ├── tailscale/ # Tailscale integrations │ ├── tailscale-api.ts # REST API client │ ├── tailscale-cli.ts # CLI wrapper │ └── index.ts # Exports ├── types.ts # Type definitions ├── logger.ts # Logging utilities └── index.ts # Entry point
src/tools/
:import { z } from "zod"; import type { ToolModule, ToolContext } from "./index.js"; const MyToolSchema = z.object({ param: z.string().describe("Description of parameter"), }); async function myTool( args: z.infer<typeof MyToolSchema>, context: ToolContext, ) { // Implementation return { content: [{ type: "text", text: "Result" }], }; } export const myTools: ToolModule = { tools: [ { name: "my_tool", description: "Description of what this tool does", inputSchema: MyToolSchema, handler: myTool, }, ], };
src/server.ts
:import { myTools } from "./tools/my-tools.js"; // In the constructor: this.toolRegistry.registerModule(myTools);
Enable debug logging for development:
# Set environment variable export LOG_LEVEL=0 # Or in .env file LOG_LEVEL=0 MCP_SERVER_LOG_FILE=debug-{timestamp}.log
View logs in real-time:
# Follow server logs tail -f logs/debug-*.log # Or use Docker logs docker-compose logs -f tailscale-mcp
Variable | Description | Required | Default |
---|---|---|---|
TAILSCALE_API_KEY | Tailscale API key | Yes* | - |
TAILSCALE_TAILNET | Tailscale tailnet name | Yes* | - |
TAILSCALE_API_BASE_URL | API base URL | No | https://api.tailscale.com |
LOG_LEVEL | Logging level (0-3) | No | 1 (INFO) |
MCP_SERVER_LOG_FILE | Server log file path (supports {timestamp}) | No | - |
*Required for API-based operations. CLI operations work without API credentials.
git checkout -b feature/amazing-feature
npm test
git commit -m 'Add amazing feature'
git push origin feature/amazing-feature
MIT License - see LICENSE file for details.
See CHANGELOG.md for version history and updates.