What it takes to sit in the middle of everything
The earlier posts made the case for lazy discovery. This weekend was the less glamorous follow-on: getting Toolport to reach more clients, hardening the part that holds your credentials, and cutting the setup down to a few clicks.
The earlier posts here made an argument. Loading every MCP server’s tool list into context on every request is a tax worth removing; context is becoming expensive real estate; and (measured on a frontier model) you can remove most of that tax without losing a single correct answer. I still think all of that holds. But being right about the idea is not the same as having something people leave installed.
Toolport only works if it sits in the middle of every tool call and you forget it’s there. That turns out to be a demanding place to sit: it has to reach whatever client you actually use, stay safe enough to hold your credentials, and not be such a slog to set up that you quit partway through. That’s where the weekend went, across three releases.
Reach
For a while Toolport really only helped if your client already spoke MCP over stdio. Claude Desktop, Cursor, that crowd. A lot of setups don’t. Open WebUI kept coming up from actual users, and the only path in was a separate Python proxy (mcpo) sitting between it and the gateway. Telling someone to install a bridge so they can use your bridge is not a great look.
So the gateway speaks HTTP and OpenAPI directly now. Run it with --http <port> and it serves an OpenAPI spec plus one POST endpoint per tool. Open WebUI, or anything that reads OpenAPI, connects straight to it. No proxy, no Python. Underneath it’s the same request path as stdio, so lazy discovery and result-shaping behave the same regardless of how a client connected. There’s a toggle in Settings that starts the gateway, hands you the URL, and actually checks that it came up instead of just claiming success.
That grew a second half almost immediately. The HTTP bridge is multi-tenant: you register clients, each with its own bearer token and profile, and one process serves all of them while resolving every request down to the servers that token is allowed to see. Two Open WebUI instances can point at the same Toolport and get completely different tools. I didn’t plan that as a headline feature, but the second something is reachable over HTTP, “who gets to see what” stops being hypothetical.
Trust
Which is the part I’d been quietly nervous about. Something that holds your credentials and routes your prompts has no business being sloppy, and opening an HTTP surface is exactly the kind of change that grows your attack surface while you’re looking the other way. So a chunk of the weekend went to plumbing nobody will ever see in a screenshot.
The HTTP endpoint requires a bearer token now. Binding to localhost feels safe but it isn’t on its own: a web page open in your browser can POST to that port and run your tools. The token is what stops it. The gateway also refuses to bind a non-loopback host without one, compares the token in constant time, and won’t reflect a caller’s Origin or send credentials cross-site.
Then a batch of smaller things. The SSRF connect-guard blocks servers pointed at link-local and cloud-metadata addresses, including the IPv6 metadata address and not just the IPv4 169.254.x one everybody remembers. Importing a server aimed at a private or internal host warns you first. A scoped HTTP client’s toolport_status no longer leaks other tenants’ server names, commands, or URLs. Config reads reject device and FIFO files and cap their size, so a crafted or symlinked config can’t eat all your memory. Most of these came out of actually auditing the new surface rather than assuming loopback would cover for me.
Friction
The last one is the problem I underrated for too long. Lazy discovery saves you nothing until you’ve connected some servers, and connecting servers is the boring part where people bail. Find the catalog, add a server, go dig up where this provider buried its API token, come back, repeat four more times. That’s a lot of activation energy for a payoff you can’t see yet.
So the catalog leads with Stacks now. A stack is a named bundle for a kind of work: full-stack web, backend and data, infra and DevOps, research and docs, plus a founder/indie-SaaS one. Pick a stack, hit “Add 5,” and every server you don’t already have goes in together. Then a “Setup steps” panel tells you per server which credential to make and links straight to that provider’s token page, so the scavenger hunt turns into a checklist. The stacks resolve against the catalog when the app builds, so a server name I typo’d fails a test instead of shipping a dead button.
This sits on a UI I’d rebuilt earlier in the weekend. The server list went from chunky three-column cards to dense grouped rows, roughly 2 to 3x denser once you pass twenty servers, with row actions that are real keyboard-reachable buttons. Global policy moved out of the Playground into its own Settings view. Activity got quieter and leads with errors. Destructive actions ask first and tell you what survives. And the catalog kept growing (Perplexity, Kubernetes, Todoist, Linode, others), because a bundle is only as useful as the servers it can pull from.
Where that leaves it
Three releases in a weekend looks like a lot, and the changelog has the blow-by-blow if you want it. But none of it really moved the idea forward. It was about whether you’d trust Toolport enough to leave it running in front of your tool calls. That kind of work doesn’t demo as well as a 91% token cut, and it’s most of the reason anybody keeps a thing installed.
It’s still local-first and open source, MIT licensed.