Notes

A pasted config fails in silence

Connecting an assistant meant pasting a URL into a file, and two of our six copies were wrong with no error. Now each client gets a plugin, link or correct block.

Every client gets the most official installable thing it actually has, and a client that has none gets a block that is correct rather than invented. We decided that after finding that two of the six config blocks we told people to paste were wrong, and that a hand-copied config fails where neither side can see it.

This post is the two failures, what we ship for each client now, and why we left four clients with nothing new.

Two copies that could not connect anything

Until this decision, the whole route from "I have an assistant" to "my assistant can use juudd" was a string a person copies. Six blocks, one per client, each ending with somebody pasting a URL into a file. Looking at whether that could be better turned up two mistakes that had been live for some time.

The setup document named an address that does not answer. It said https://mcp.juudd.com. Measured on 2026-09-03:

RequestAnswer
POST https://mcp.juudd.com404
POST https://mcp.juudd.com/mcp401, alive and asking for a token

The server names its own resource, and the document named a different one. The landing page was right, because it reads the connector address from its build. The document an assistant reads in order to connect itself was the one that could not connect anything.

The VS Code block would have been ignored without a word. VS Code's .vscode/mcp.json takes servers, not mcpServers, and wants an explicit type, where Cursor and Claude Desktop infer one. VS Code does not warn, error or log. It loads no server and says nothing, so a reader who followed the instruction exactly concludes the connector is broken.

Both are fixed. They sit in the argument, not in the footnotes, because they show the shape of the problem: the person sees nothing happen, and we see nothing at all.

What each client gets now

Claude Code gets a plugin, because Claude Code has plugins. It holds the connector declaration and one skill. The skill is why a plugin beats a one-line claude mcp add. Half of what an assistant needs is not setup, it is rules: no bare imports in server code, .js and not .ts, a row-level security policy on every table, a deploy that replaces rather than patches, and transfer_database being a write rather than a read. Each of those is a refusal this platform issues on purpose. A tool should say what it will refuse before it refuses it, and a plugin is that idea one level up: the rules arrive with the connector instead of one error at a time.

The marketplace is a URL on our own site, not a repository. claude plugin marketplace add accepts a repository, a git URL, a local path, or an https URL that serves marketplace.json. Ours is private, so the first three reach nobody. The URL form needs no account and no token. It comes with one documented constraint: a marketplace added by URL downloads only that one file, so a relative path to the plugin resolves to nothing. The plugin therefore ships as a zip, and the marketplace names its sha256, so a client refuses any zip that is not the one we built.

The zip is reproducible, and that is not tidiness. Same inputs, same bytes, same digest: entries sorted, timestamps fixed, line endings normalised, nothing about the building machine inside. Without that, every build publishes a new digest for an unchanged plugin. A customer downloading during a deploy then gets a zip the marketplace no longer names, and their client is right to refuse it.

Cursor and VS Code get an install link each. Both clients publish a link scheme, and both links are built from the connector address like every command on that page. For VS Code the link carries the server's name and type as well as the address, because it does not infer a transport.

The config text stays underneath, on every client. Two readers need it. One is the person who wants to see what is about to be written to their machine before it is written. The other is an assistant, which cannot click a link. A one-click path that removed the text would trade our actual way of reaching people for a button.

Four clients get nothing new, on purpose

Codex has no installable artifact for a remote server, and its config block is already the documented form. Claude Desktop and claude.ai are set up by hand, and listed through a directory submission, as is ChatGPT. We considered a VS Code extension and did not take it: it is a second artifact to keep in step with the connector, and it buys a listing next to an install link that already connects someone in one click.

Inventing an install route a client does not have would be the same mistake as the wrong address, with a better-looking surface.

What we watched, and what we could not

We ran it against the real client before saying it works. The plugin validated. Adding the marketplace from a local copy worked. Installing from that local copy was refused, because the client will not fetch an archive from a loopback address. That is the client being right, and it means the install step cannot be rehearsed locally at all: only a real https origin can test it.

So we deployed and then watched it. The marketplace answered, the zip's digest matched the one named, claude plugin install installed it, and the installed copy carried the connector declaration and the skill. The digest published is the one a Linux build and a Windows build now both produce, which is the line-ending fix being right rather than merely asserted.

The rule, once

For each client, ship the most official installable artifact it really has, keep the readable config underneath it, and where a client has none, publish a block that is correct instead of one that merely looks complete. The tools and their limits are listed in the docs.