How sign-in works
The server validates every inbound request and acts as an OAuth resource server. Validation. Inbound Supabase access tokens are verified as ES256 against the project’s JWKS, with audienceauthenticated. The backend re-validates the same token, so a request
is checked twice (defense in depth).
Discovery. The server advertises Supabase as its authorization server using two
discovery documents: OAuth 2.0 Protected Resource metadata (RFC 9728) at
/.well-known/oauth-protected-resource, and Authorization Server metadata (RFC 8414) at
/.well-known/oauth-authorization-server. Supabase serves its OAuth metadata at
/.well-known/openid-configuration rather than the RFC 8414 path, so the server forwards
the OIDC document at the RFC 8414 path and injects a registration_endpoint (Supabase’s
Dynamic Client Registration endpoint, which the OIDC document omits).
That metadata is what lets a client (Claude Code, Cursor, and others) bootstrap sign-in
with no pre-issued token: it discovers Supabase, registers itself over Dynamic Client
Registration, runs the OAuth code flow, and presents the resulting access token to the
server.
OAuthProxy
The server fronts Supabase with a FastMCPOAuthProxy instead of pointing clients straight
at Supabase.
Why it exists. Supabase’s OAuth server validates redirect_uri by exact string match
and does not implement the RFC 8252 loopback exception (where an auth server ignores the
port for http://127.0.0.1 and http://localhost redirects). A client that binds a fresh
ephemeral loopback port per session, with VS Code being the notable one, reuses a cached
registered client_id whose redirect_uris no longer match the port it bound, so Supabase
rejects the authorize request with invalid redirect_uri. Cursor, Claude Code, and the app
builders keep a consistent redirect through register, authorize, and callback, so they never
hit this.
The proxy is why VS Code and other ephemeral-loopback-port clients sign in at all. Without
it, a cached
client_id whose registered ports no longer match would fail at the authorize
step. You do not configure any of this; the client picks its port and the proxy absorbs it.Token forwarding
Tools never read headers or the local config directly. Each tool obtains theAuthorization header to send to api.ishlabs.io through a single chokepoint.
The forwarded token is the validated access token, which is the upstream Supabase JWT. The
inbound bearer is a short reference token the proxy mints to the client; the proxy resolves
it server-side to the stored upstream Supabase JWT, and that JWT is what gets forwarded. If
the resolved access-token context is unavailable, the server forwards the inbound
Authorization header verbatim; a request with no bearer is rejected.
The backend re-validates whatever token it receives, so forwarding is defense in depth
rather than the only check.
Confirm the session
Read theish://identity/me resource, or call a read-only tool
like workspace_get, to see whose account the session is acting as. A read draws no
credits. See Connecting for the full check.
See also
Connecting
Add the server to your client and sign in, step by step.
Tool conventions
Naming, id prefixes, polymorphism, and safety annotations.
MCP resources
Session and reference data, including
ish://identity/me.