How to connect an MCP server on Tailscale to Claude and ChatGPT
Claude.ai, ChatGPT and Grok can't reach your tailnet. Publish your MCP server with Tailscale Funnel, protect it, and add it to every assistant with Upsy.
Updated
Short answer
This guide is for an MCP server you run on a machine in your tailnet (your Tailscale network), such as a home server. Claude.ai, ChatGPT, Grok and Muse connect from their companies' clouds, so they can't reach it. Publish it with Tailscale Funnel, which gives it a public https://<machine>.<tailnet>.ts.net address. Add that address to each assistant, or once to Upsy, which shares it with all of them at the limits you set. It takes about ten minutes. The server then needs its own key or sign-in.
Want an MCP server that manages Tailscale itself? That's different. Tailscale's AI gateway, Aperture, added Tailscale and Tailscale SSH MCP endpoints in August 2026, and community servers such as HexSleeves/tailscale-mcp use the Tailscale CLI and API.
Who can reach a server on your tailnet
- Local agents, directly. Claude Code, Codex, Cursor or Hermes on a tailnet machine reach the server by its MagicDNS name or Tailscale IP. For an HTTPS address only your tailnet can open, use
tailscale serve. No Funnel or Upsy needed. - Not cloud assistants. Claude's custom connectors connect from Anthropic's cloud. ChatGPT and Grok connect from theirs, and Muse runs on its own computer in the cloud. xAI says it plainly: "Your MCP server must be reachable over the public internet" (Grok connectors). Upsy runs in the cloud too.
- The assistants' own tunnels. Claude's MCP tunnels are a research preview for Enterprise organizations. ChatGPT's Secure MCP Tunnel runs a
tunnel-clientin your network. Neither uses Tailscale.
Serve or Funnel
| Tailscale Serve | Tailscale Funnel | |
|---|---|---|
| Who can open the address | Devices on your tailnet | Anyone on the internet |
| Use it for | Local agents | Claude, ChatGPT, Grok, Muse, Upsy |
Funnel traffic passes through Tailscale relays that can't decrypt it. TLS ends on your machine, and its IP address stays hidden. Bandwidth is limited, and a port can be Serve or Funnel, not both (Funnel docs).
What you need
- An MCP server that speaks Streamable HTTP on a port of that machine. Upsy speaks only Streamable HTTP; a stdio server needs a wrapper (below).
- Tailscale 1.38.3 or later, on a platform that runs the Tailscale CLI. On a Mac, Funnel depends on which Tailscale app you installed; Tailscale's docs list them.
- MagicDNS, HTTPS certificates and the
funnelnode attribute for your tailnet. Changing the policy file takes an Owner, Admin or Network admin. - A key or OAuth on the server, since the address will be public.
Step 1: publish the server with Funnel
In the admin console's DNS page, turn on MagicDNS, then Enable HTTPS under HTTPS Certificates. Machine names get published in a public certificate ledger, so rename any that say too much (Tailscale's HTTPS guide).
On the Access controls page, expand Funnel and select Add Funnel to policy. Or skip this: the first time you run Funnel, Tailscale opens a page to approve it and adds the attribute and certificates itself.
On the server's machine, start Funnel with your server's port, here 8000:
tailscale funnel --bg 8000--bgkeeps it running after you close the terminal. Funnel forwards public HTTPS on port 443 tohttp://127.0.0.1:8000and prints the address, such ashttps://homelab.tail1234.ts.net.Add the MCP path, often
/mcp:https://homelab.tail1234.ts.net/mcp.
A new address can take up to 10 minutes to appear in public DNS. tailscale funnel status shows what's published (Funnel CLI).
If your server only speaks stdio
supergateway serves a stdio server over Streamable HTTP at /mcp. Since version 4.2, --apiKey makes every request carry a key and --host limits where it listens:
npx -y supergateway --stdio "uvx mcp-server-time" \
--outputTransport streamableHttp --port 8000 --host 127.0.0.1 --apiKey "$MCP_API_KEY"
Swap in your server's command, then run Funnel on port 8000. Clients send the key as Authorization: Bearer <key>, as Upsy does.
Option A: add the Funnel address to each assistant
Each assistant then calls your server directly. What matters is the sign-in it accepts:
- Claude: Customize › Connectors, then Add › Custom › Web (or Add custom connector on some accounts). Paste the address, click Continue twice, then Add and Connect. It uses OAuth or No sign-in; an API key under Request headers is a beta for a few organizations (Anthropic's docs). See Claude custom connectors.
- ChatGPT: Plugins › Add › Create custom MCP server. Authentication is OAuth, none, or a mix (OpenAI's docs), with no field for a fixed key. See ChatGPT custom MCP servers.
- Grok: on grok.com, Connectors › New Connector › Custom, then the server's OAuth or API key step (xAI's docs). See Grok custom connectors.
- Muse: ask it in a chat to add a custom connector. See Muse custom connectors.
Fine for a server with OAuth. With a key-only server, most Claude and ChatGPT users can't send the key, and adding it with no sign-in opens it to anyone. You also repeat the setup in every assistant.
Option B: add it once to Upsy
Upsy is one MCP server for all your assistants. It keeps your server's key, and each assistant signs in to Upsy with OAuth, so a key-only server works in Claude and ChatGPT too.
- Sign up at upsy.ai with Set up Upsy.
- Open Apps, click Connect an app, and under Any MCP server click Add on the MCP server on Tailscale card.
- Enter a Name assistants will see, such as Homelab, and the Funnel address with its path under MCP Endpoint.
- Paste the server's key under API key or token; Upsy sends it as a Bearer token. Leave it empty for a server with OAuth: Upsy finds the sign-in in its metadata and sends you there.
- Click Add MCP Server. Upsy lists the server's tools to check it works. If it can't, it says why and saves nothing.
- The server starts at No access for the assistants you've already added. Click Check which assistants can use it in the banner and pick Read-only, Full access or Pick actions… for each.
No assistants yet? Under Assistants, click Add assistant and pick one under Which assistant?: Copy prompt for Grok and Muse, a custom connector at https://upsy.ai/connect for Claude and ChatGPT. On Upsy's sign-in page your server is ticked at All; switch it to Read-only if you like.
Assistants reach its tools through Upsy's app_tools, app_read and app_call. Start a new chat if one doesn't see it.
Check that it works
Using Upsy, list the tools on my Homelab server, then run one that only reads.
The assistant should list the tools and run one, and the call shows in Upsy's History under that assistant.
Access levels for your own server
- Read-only allows only tools your server marks
readOnlyHint: true, and never one whose name says it changes something (create, delete, send, update…). If your server doesn't label its tools, Read-only allows nothing; use Pick actions. - Pick actions lets you choose tools one by one. Tools the server adds later stay off until you pick them.
- Full access allows every tool. No access hides the server.
Troubleshooting
"Use a public https:// address. On Tailscale? Use the server's Funnel address (https://….ts.net)."
You entered a tailnet address: a MagicDNS name like http://homelab:8080/mcp, a Tailscale IP (100.64.0.0/10 or fd7a:115c:a1e0::/48), or an http:// ts.net address. Upsy only reaches public https:// addresses. Use the Funnel address.
"Couldn't reach Homelab. Turn on Tailscale Funnel for it…"
The ts.net address didn't answer from the internet. Run tailscale funnel status on the machine. A new address can take 10 minutes to resolve. Without --bg, closing the terminal stops Funnel.
"Couldn't use Homelab: …" or "Homelab didn't accept the token, or couldn't be reached: …"
The address answered, but the MCP request failed. Check:
- The port. Funnel's port must match your server's. The public port must be 443, 8443 or 10000; with
--https=8443, keep:8443in the address. - Where the server listens. Funnel sends traffic to
http://127.0.0.1:<port>, so a server bound only to its Tailscale IP, or in a container without a published port, won't answer.curl http://127.0.0.1:8000/mcpon the machine should get an HTTP answer, even an error, not "connection refused". - The path, usually
/mcp. - The transport. An SSE-only server (often at
/sse) or a stdio server needs a wrapper such as supergateway. - The key. Upsy sends
Authorization: Bearer <key>. A server that reads another header, such asX-API-Key, won't see it.
It worked, then stopped
If Apps shows Reconnect and assistants get "Homelab refused its token", the server no longer accepts its key. Remove it on its page and add it again with a new key. A server with OAuth has a Reconnect button there instead.
A new tool doesn't show up
Upsy keeps each server's tool list for up to an hour. Wait, or remove the server and add it again.
Security and privacy
- Funnel is public. Anyone who finds the address can send requests. Never publish an MCP server without its own key or OAuth.
- Your key stays in Upsy, in your own storage. Assistants call Upsy, and Upsy calls your server, only at public internet addresses.
- History lists every call to your server under the assistant that made it.
- Alerts email you when a server is added, and when one assistant deletes 50+, sends 20+ or reads 100+ items in 10 minutes. Your server's tools count by name, such as
delete_…,send_…orget_…. - No approval step. Upsy doesn't ask before each call, so keep tools that change things behind Read-only or Pick actions.
- Turning it off: set the server to No access, click Remove on its page in Upsy, or run
tailscale funnel reseton the machine. Removing thefunnelattribute from the policy stops Funnel for the whole tailnet.
FAQ
Is there an official Tailscale MCP server?
Tailscale's own MCP endpoints are part of Aperture, for agents working with your tailnet. The ones on GitHub are community projects. Neither puts your own server in front of cloud assistants; Funnel does.
Can Claude connect to an MCP server on my tailnet?
Claude Code can, from a tailnet machine. Claude's custom connectors can't: they connect from Anthropic's cloud, so publish the server with Funnel first.
Can ChatGPT connect to a local MCP server?
Not directly. Publish it at a public HTTPS address with Funnel, or set up OpenAI's Secure MCP Tunnel.
What is a Tailscale MCP gateway?
Tailscale's own is Aperture, which passes model and MCP traffic for people and agents on your tailnet. Upsy works the other way: a gateway in the cloud that cloud assistants can reach, which calls your Funnel address at each assistant's limits.
Is Tailscale Funnel safe for an MCP server?
Traffic is encrypted to your machine and your IP stays hidden, but the address is public. Use a long random key or OAuth, Read-only where you can, and turn Funnel off when you don't need it.
Related guides
- How to share memory between ChatGPT, Claude and GrokStop repeating yourself. Move your memory from ChatGPT to Claude, or keep one memory that ChatGPT, Claude, Grok and Muse all read and you control.
- Grok Bot vs Muse: which personal AI agent should you use?Grok Bot and Meta's Muse compared: price, the apps they connect to, browser, memory and safety. And how to use both with the same apps and memory.
- How to add a custom connector to Meta MuseMuse adds custom connectors from its chat. How to add a remote MCP server to Muse, approve the sign-in, and check that its tools work.
- How to connect Gmail to GrokConnect Gmail to Grok so it can search, read, draft and send your email. Grok's built-in connector, its limits, and how to choose what Grok may do.
- How to connect multiple Gmail accounts to ChatGPTChatGPT now connects more than one Gmail account. How to add a second inbox, and how to give each one its own access in ChatGPT and your other assistants.
- How to connect multiple Gmail accounts to ClaudeClaude's Gmail connector takes one Google account at a time. Connect your work and personal Gmail to Claude at once, up to five, each with its own access.