Building Whet: lessons from an agent-native product
Three decisions that mattered when shipping a product where the CLI and the MCP server are first-class citizens, not afterthoughts.
Most products bolt agents on at the end. Whet was built the other way around: the CLI and the MCP endpoint came before the workbench was polished. Three decisions did most of the work.
Share what’s expensive to drift — and only that
The original instinct was “one OpenAPI spec, three surfaces consume it.” That turned out to be the wrong unit of sharing. Workbench, CLI, and MCP all have different shapes — the workbench wants UI-shaped responses, the MCP wants tool descriptions, the CLI wants narrow command-shaped endpoints. Forcing them through one schema fights all three.
What we actually share is narrower and stricter: a single bearer token across REST and MCP, and a generated TypeScript type bundle the CLI imports from a hand-maintained spec. The MCP keeps its own tool registry. The workbench keeps its own client. Each surface owns its shape; the only thing locked is the auth contract — because that’s the one place where drift would be expensive.
The general rule: identify the one piece where drift hurts, and lock that. Don’t try to lock everything.
Auth has to be invisible
Agents fail loudly when auth is hard. They don’t have hands for a device-code flow and can’t scan a QR. The MCP endpoint accepts the same bearer token as the REST API — one credential, one issuer, no separate agent flow. The rule we landed on: if a human can sign in once and forget, an agent should get the same access on the same credentials. Anything that requires a second auth step is anti-agent by construction.
MCP doesn’t need to be a separate binary
Most MCP tutorials default to a standalone stdio server you ship and install. For a product that already has a web app, that’s a needless second deploy unit, a second auth boundary, and a second observability surface. Whet’s MCP server is an HTTP route in the Next.js app, served over Streamable HTTP with the same bearer token as everything else.
Co-locating it removed an entire ops surface. Same deploy, same logs, same env vars, same access control. The stdio bridge still exists for clients that need one — it’s a 150-line forwarder that injects the bearer token. The actual MCP server lives next to the workbench, where the data already is.