fluidrecall.com · docs
Personal Agent Protocol
Fluid Recall speaks the Personal Agent Protocol (Poppy) version 0.1. A personal agent can find Fluid Recall on its own, start a Session for its user, and ask that person to sign in with exactly the access they choose: view only, change only, or both.
Poppy sits beside the existing doors. The MCP server, the JSON API, and the ChatGPT plugin's OAuth flow work exactly as before, and personal API tokens keep full access.
Last updated 2026-10-10.
1. Discovery
GET https://fluidrecall.com/.well-known/poppy.json names the organization (Fluid Recall, fluidrecall.com), the issuer https://fluidrecall.com, the scopes a person can grant, and two interfaces:
- the MCP server at
POST https://fluidrecall.com/mcp, stateless Streamable HTTP; - the API at
https://fluidrecall.com/api/v1, described byhttps://fluidrecall.com/api/openapi.json.
The issuer's metadata at /.well-known/oauth-authorization-server lists fluidrecall.com in poppy_domains along with the token, authorization, and revocation endpoints.
2. Sessions and Session Tokens
A personal agent identifies itself with a Client ID Metadata Document: an HTTPS URL that serves its name, logo, keys, and redirect addresses. It authenticates with private_key_jwt. Its key set and redirect addresses must live on its own domain.
To start a Session the agent posts the JWT bearer grant to POST https://fluidrecall.com/oauth/token with a short assertion naming its user. Fluid Recall answers with a session_id, a Session Token that lasts one hour, and signed_in: false. A Session starts signed out and lasts up to 30 days. The agent renews the Session Token by sending the same grant with its session_id.
Session Tokens for the API are bound to the agent's key with DPoP, so every call carries a fresh proof. For MCP, the agent asks for a Bearer Session Token by sending resource=https://fluidrecall.com/mcp. That token works only at the MCP server. Tokens are never accepted in a URL.
3. Direct Sign-In: view or change
To sign in, the agent sends the person to https://fluidrecall.com/oauth/authorize with PKCE S256 and the scopes it wants. This is the same consent page the ChatGPT plugin uses. It shows the agent's name, logo, and domain, and lets the person tick what to allow:
poppy:read, view: decks, cards, the due queue, study settings, and the inbox;poppy:write, change: add and edit cards, record reviews, change settings, and manage decks.
The two scopes are independent. Change does not include view. The person can create a free account on the spot or link an existing one with its personal API token. Declining, or allowing nothing, sends the agent access_denied. Every redirect carries iss=https://fluidrecall.com.
The agent exchanges the code at the token endpoint with its session_id. That signs the Session in and returns an Account Token that lasts up to 90 days. Later the agent can use the Account Token to sign in a new Session without asking the person again, optionally with fewer scopes.
4. What each scope allows
Fluid Recall checks scopes on every MCP tool and API route. A Session that is still signed out gets 403 with error="sign_in_required". A view-only Session that tries to change something gets 403 with error="insufficient_scope" and scope="poppy:write" in WWW-Authenticate, and nothing is written. Session Tokens can never list, mint, rotate, or revoke personal API tokens.
5. Signing out
The agent revokes its Account Token at POST https://fluidrecall.com/oauth/revoke, signed with its client assertion. Every Session that token signed in is signed out at once and continues signed out.
What is not supported yet
Fluid Recall implements direct sign-in only. Device sign-in, mediated sign-in, custom scopes, web pages for agents, and protocol extensions are not offered, and poppy.json does not claim them. DPoP nonces are not issued. There is no account page for disconnecting an agent; the agent's revocation call is the way to sign out.
Elsewhere on this site
Read the ChatGPT plugin walkthrough for the OAuth flow the plugin uses, the FAQ, or the machine-readable llms.txt.