chadtmiller.com/knotless

Git hosted in your atproto account, on any stock PDS, fast enough for agents.

git clone knotless://chadtmiller.com/knotless

needs the knotless git helper. set it up

MCP over HTTP: show where sign-in goes; revoke and rotate tokens

Open chadtmiller.com wants to merge into main from chadtmiller.com/knotless:mcp/consent-host-and-revocation 1 comment
chadtmiller.com opened on Oct 22, 2026

Two fixes to the /mcp authorization server.

Consent page names the redirect host. client_name is whatever a client registers with, so anyone could register as "Claude" with their own redirect, send a listed user an authorize link, and walk off with the code. The form now says "Signing in sends you back to host" and tells the user to stop if that isn't where they meant to connect.

Revocation and refresh rotation. Each (DID, client) pair has a not-before time in mcp/<did>/revoked/<sha256(client_id)>. Tokens carry an issued claim (micros) and are good only if issued >= not_before.

  • Every sign-in and refresh moves the not-before time to the new tokens' issue time, so only the newest pair works and a refresh token works once. Reconnecting a client also kills that client's old tokens.
  • POST /mcp/revoke (RFC 7009, advertised in metadata) voids all of a client's tokens for the account. Unknown tokens get 200, per spec.
  • Tokens issued before this change have no issued and keep working until the client's next refresh.

Tradeoff: if a client loses the response to a refresh and retries with the old refresh token, it has to reconnect.

Tests cover the host on both form paths, rotation, the revoke endpoint, and a failed write (500 server_error).

chadtmiller.com commented on Oct 22, 2026

Update: dropped refresh rotation. A refresh no longer voids the client's earlier tokens. Only a new sign-in and /mcp/revoke move the not-before time. That removes the reconnect tradeoff from the description: retried or parallel refreshes and in-flight requests keep working. A leaked refresh token now stays valid until revoked, reconnected, or expired (90 days), which is fine for an allowlisted server. The write-failure test now goes through /mcp/revoke.