A small macOS LaunchAgent that monitors whether Claude Desktop can reach a self-hosted MCP server over Tailscale, and sends an ntfy notification when it can.
Claude Desktop on macOS runs in a sandbox that blocks connections to Tailscale
addresses (both 100.x.x.x IPs and *.ts.net hostnames). This means even if
your MCP server is correctly configured and reachable from everywhere else on
your tailnet, Claude Desktop can't connect to it directly.
The practical workaround is to expose the MCP server via a Cloudflare Tunnel (or similar public HTTPS endpoint) so Claude Desktop has a reachable URL. This script exists because that sandbox behaviour could change in a future macOS version — it runs daily and notifies you the moment a direct Tailscale connection becomes possible, so you can switch back to the private endpoint.
A 405 response from the MCP endpoint is expected and treated as healthy — it
just means the server is rejecting a plain GET on /mcp, which is correct
behaviour for an MCP server.
Open tailscale-mcp-check.sh and set the two variables at the top:
TAILSCALE_URL— your Tailscale MCP server URL
e.g.https://your-hostname.your-tailnet.ts.net/mcpNTFY_URL— your ntfy endpoint and topic
e.g.https://ntfy.example.com/your-topic
If you're self-hosting ntfy, make sure the topic is one you're subscribed to.
cp tailscale-mcp-check.sh /usr/local/bin/tailscale-mcp-check.sh
chmod +x /usr/local/bin/tailscale-mcp-check.shRename the plist file to match your preferred label (replace com.user with
something that makes sense for you), then install it:
cp com.user.tailscale-mcp-check.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.user.tailscale-mcp-check.plistThe job runs daily at 09:00. Adjust Hour and Minute in the plist to suit.
bash /usr/local/bin/tailscale-mcp-check.shNo output means the endpoint wasn't reachable (expected while the sandbox restriction is in place). You'll get an ntfy notification the first time it is.