AI Part 6: Connector Quirks, Cache Traps, and What I'd Do Differently

Six months in. This is the post I wanted to read before I started and couldn’t find: the operational notes, the surprises, and the short list of decisions I’d make differently if I were doing this again from scratch.

The cache layer you don’t see

Every MCP client maintains a local cache of the tools your server exposes — names, descriptions, parameter schemas. This cache is what the model actually consults when choosing which tool to call. Your server can advertise a new tool, restart cleanly, log “listening” — and the client will keep using yesterday’s tool list until something forces a refresh.

What forces a refresh varies. Sometimes a connector reconnect is enough. Sometimes the connector reconnects but the tool catalogue doesn’t, and you have to fully relaunch the client. The signal that you’re in this state is: your tool calls succeed but the new tool you just shipped doesn’t appear in the list, even though the server has it. If you’re debugging “why isn’t the model calling my new tool”, check the catalogue cache before you check the tool.

I now treat catalogue refresh as an explicit step in any tool deploy: ship the server, restart, then explicitly verify the catalogue has the new tool name before claiming the deploy is done.

OAuth refresh edge cases

The single non-obvious thing about OAuth in a personal MCP is what happens to in-flight sessions when the server restarts. If your tokens are in memory only, every restart invalidates every token, the client mid-session gets a 401, and depending on the client’s retry behaviour, your conversation either reconnects gracefully or hangs.

The fix is to persist tokens to disk and reload on startup. Mine survive restarts. Refresh tokens rotate on use, which means a stolen refresh token stops working the next time the legitimate client refreshes — a property I’d want even on a single-user system.

The edge case I missed for a while: tokens that expire while the server is down. They’re still in the persistent store, they look valid, but the expiry timestamp is in the past. The expiry-cleanup sweep runs on a timer, which doesn’t run while the server is down, so on first startup you can have stale tokens around for up to one sweep interval. Cheap fix: run the expiry sweep once at startup, before accepting requests.

Egress and network gotchas

If your client is sandboxed (and most are these days), it has an egress allowlist of domains it will connect to. Adding your MCP host to that allowlist sometimes requires restarting the client for the change to take effect. I lost half an hour once to an “unreachable” connector that was just a stale allowlist in memory.

Two corollaries: pick a stable hostname for your MCP server up front; you’ll spend the next year typing it into other tools. And put the server behind TLS from day one, even on a private network — most clients refuse plain HTTP, and you don’t want to discover that mid-debug.

Unit-file surprises

This one is specific to a particular pasting workflow but it bit me hard enough to mention. Some chat clients render certain URL-shaped strings as auto-links when you paste configuration through them. If the configuration is then re-saved into a system file, the auto-linking can corrupt it in ways that don’t show up until something parses the file.

The lesson is broader than the specific case: don’t paste configuration through a rich-text intermediary if you can avoid it. Edit configuration files in place, on the box, with a text editor that doesn’t reformat what it sees.

What I’d do differently

If I were starting again with what I know now, in order of impact:

  1. Build the audit log on day one. I added it after a week of squinting at server logs trying to reconstruct what the agent had done. The audit log is the cheapest thing in the project and the one I rely on most.
  2. Build the delete tool before I needed it. I lived with read and write for a month, accumulating probe artefacts and stale files I couldn’t easily clean up without logging into the box. Adding the delete tool took twenty minutes and removed a recurring annoyance.
  3. Persist tokens before going public. I had a brief window where every restart broke the session. It wasn’t catastrophic, but it made me afraid to deploy server changes, which is the wrong relationship to have with your own server.
  4. Write the tool descriptions like you mean it. The first descriptions I wrote were terse and the model picked wrong tools constantly. The fix wasn’t smarter prompts; it was descriptions that did their job. Hours of rewriting saved by ten minutes of careful description-writing.
  5. Resist the urge to add tools. The most-used tools in the surface are the boring ones — read, write, deploy. The “clever” tools I added later (with parameters, options, modes) get called less and confuse the model more.

Closing note

The version of this project I’d hold up as a recommendation to other people is smaller than the version I have. Five tools, four safety rails, one audit log, one boring deploy script. Everything else is something I added because it seemed neat at the time. If you’re building one of these, start there. Add the next thing only when you’ve felt the absence of it.

That’s the series. The patterns in these six posts are most of what I know about doing this well. The rest I’ll learn the same way I learned these — by getting it wrong first.