All posts
Sep 11, 2026·2 min read

ChatGPT Plus can call a write tool on your self-hosted MCP server

#chatgpt#debugging#mcp#self-hosting#tailscale

Tested September 2026. ChatGPT's connector support changes often.

I wanted ChatGPT to hand work to agents on my own machine: look at the queue, write a job, and my server picks it up. That means a Plus account calling a tool that writes, on an MCP server I host myself.

I'd read that Plus can't do this, and my first attempt agreed. ChatGPT connected, then nothing. No tool call, no error. It looked like my plan wouldn't allow it.

The plan was fine. My server was answering with the wrong protocol version.

What the logs showed

The server logged every inbound request, so I could see where it stopped:

  1. ChatGPT sent initialize asking for protocol version 2025-11-25.
  2. My server didn't have that version in its list, so it replied with its newest, 2026-07-28.
  3. ChatGPT went silent. No tools/list, nothing in the UI.

That's the MCP spec working as written: if the server can't match the client's version, a client that can't use the server's version disconnects. ChatGPT just didn't tell anyone.

It's also a bigger mismatch than two dates suggest. 2026-07-28 is the stateless revision of MCP and drops the initialize handshake entirely, so my server was answering a handshake with a version that doesn't have one.

The fix was one line, adding 2025-11-25 to the supported list. ChatGPT then listed the tools, called the write tool, and a job appeared on my machine. On Plus, no upgrade.

I'd bet plenty of "Plus can't do write connectors" reports are this same failure. From the chat window, a client quietly hanging up looks exactly like a feature your plan doesn't include.

Three traps along the way

Curling your own tunnel URL proves nothing. I exposed the server with Tailscale Funnel and curled the public ts.net URL from my laptop: 200. But on any device already on your tailnet, MagicDNS resolves that name to the machine's private 100.x address, so it returns 200 whether Funnel works or not. A real public request carries Tailscale-Funnel-Request: ?1. Log it, and test from your phone with Tailscale switched off.

A Funnel hostname isn't a secret. Its certificate lands in public Certificate Transparency logs like any other. My OAuth "Allow" page had no login in front of it at first. Anyone who found the hostname could have registered a client, clicked Allow, and left with a valid token. It needs a passphrase now.

systemctl --user enable --now won't restart a running service. I rebuilt the server, reran the installer, got a success message, and the old binary kept serving. I spent a while testing a fix that wasn't running. The installer now restarts the unit explicitly.