A couple of weeks ago we wrote about why AI agents need personal tokens. The setup at the end of that post works well in Claude Code: create a token, run one command, and your agent can read bug reports.
Then people tried to add BugDump to Claude on the web, and it didn't work.
There is nowhere to paste a token in a Claude custom connector. ChatGPT doesn't have one either. VS Code will take a header if you edit its config file, but its "Add Server" flow doesn't ask for one. The MCP clients most people use expect a URL, and when the server answers 401, they expect to sign in.
So we added sign-in to our MCP server. The code was the small part. Here's what it looks like for the person connecting, and the four decisions that took most of the time.
How an MCP client signs in
You copy https://api.bugdump.com/api/mcp and add it to Claude as a custom connector, or click Add to Claude on your project's MCP page, which does the copying for you. Claude opens a BugDump page in your browser. You sign in, choose whether the app may change things or only read them, and click Allow.

Underneath, it's the flow the MCP specification describes. The first request comes back as a 401 with a WWW-Authenticate header pointing at a small JSON document. That document names the server that handles sign-in. Claude fetches that server's metadata, sends you to the sign-in page, and swaps the result for a token. None of it is specific to Claude. A client that follows the spec needs only the URL to find the sign-in page.
One connection for all your projects
Personal tokens in BugDump are bound to a single project. It's a tidy model. A token for Acme Store can't see Acme Admin, and nobody has to wonder which project the agent is working in.
We meant to keep it for sign-in too, one connection per project, maybe with a URL per project. Then we tried adding a second one. Claude won't add the same connector URL twice, and a different URL for every project means a separate connector to set up and keep track of for each. Someone with three projects would end up with three connectors, and most people would stop after the first.
So a sign-in connection belongs to you, not to a project. It reaches every project you're a member of, and every other tool takes one extra argument, project: the project's slug, which can be left out if you belong to only one project. A new tool, list_projects, tells the assistant what it can reach, including each project's key, so it knows that AS-1 lives in Acme Store.
The part we like most is what happens when the assistant forgets to say which project it means. We don't pick one for it. If you belong to more than one project, the call comes back with this:
{
"error": "MCP_PROJECT_REQUIRED",
"message": "This account belongs to several projects. Pass `project` with the slug of the one the user means.",
"projects": [
{ "slug": "acme-admin", "key": "AA", "name": "Acme Admin", "role": "OWNER" },
{ "slug": "acme-store", "key": "AS", "name": "Acme Store", "role": "OWNER" }
]
}
It comes back as the tool's own result rather than as a protocol error, so the model reads it and tries again with the right slug. It shouldn't come to that often: the server's instructions tell the assistant to call list_projects before anything else.
Membership is checked on every call. If someone leaves a project, their assistant loses access to it on the next request, and there is nothing to clean up.
Only known clients: Client ID Metadata Documents
In classic OAuth, an app is registered with the server before it can ask anyone for access, either by hand or through Dynamic Client Registration. The newer approach the MCP spec recommends, Client ID Metadata Documents, lets an app identify itself with a URL it controls instead. Claude's is a JSON file on claude.ai that, among other things, lists the addresses Claude is allowed to receive the sign-in result at.
It's a good design. On its own, though, it means anyone who can host a JSON file can turn up on your consent page under whatever name they choose.
So BugDump accepts four apps: Claude, Claude Code and VS Code by the exact URL of their document, and ChatGPT by one fixed pattern on chatgpt.com, because it publishes a document per connection. The consent page shows the app's name and the host its document lives on ("Requested by claude.ai"), which the app can't fake. Dynamic Client Registration is switched off. Cursor uses it, so Cursor keeps using a personal token, as do scripts and CI jobs. That's what tokens are good at anyway.
Checking the token, consent and account on every request
An access token lasts an hour. After that, the app quietly trades a refresh token for a new one, and that's how a connection stays alive for weeks without asking you to sign in again. The catch is that the refresh step doesn't stop to ask whether you still want the app connected, or whether your account is still active.
So our MCP endpoint asks, every time. On each request it checks that the access token exists and hasn't expired, that your consent for that app still exists, and that your account is active and not a guest. Disconnecting an app deletes its consent and every token it holds in one go, and its very next call fails with a 401 that sends it back to the sign-in page. Changing or resetting your password disconnects every app at once, which is what you want if the reason you're changing it is that something leaked.

The tokens themselves are random strings stored as hashes, just like personal tokens. There are no signing keys to rotate, and revoking a token means deleting a row.
The assistant still acts as you
Everything else stayed the same on purpose. An app connected by signing in acts as you and sees what you can see. Every change it makes shows up in the task's history and comments under your name, with a via MCP label, and the audit log records which app made it. Choose Read only and the write tools aren't registered at all: the model never sees move_task, so it can't try to call it.

That's Claude on a Safari checkout bug. It read the task, left a note on where to look first, moved it to In Progress and assigned it. To anyone reading the task later, it's clear which part came from the assistant.
What's still rough
ChatGPT needs developer mode to add a custom MCP server, and developer mode needs a paid ChatGPT plan.
Changing access means reconnecting. To give a read-only app write access, you disconnect it and connect again. We'd rather you made that choice deliberately than with a toggle you forget about, but it is an extra step.
The label doesn't name the app yet. A comment says "via MCP", not "via Claude". Every comment and history entry already stores which app made it; the task page just doesn't show it yet.
Connecting BugDump to Claude, ChatGPT or VS Code
Open any project's MCP server page and click Add to Claude, or copy the URL into ChatGPT or VS Code. The steps for each app are in Connecting Claude, ChatGPT or VS Code to BugDump. If you're on Cursor or wiring up a script, personal tokens still work exactly as before: see Using BugDump with Claude Code (MCP).