Find the connector
Give the agent host the connector address and nothing else. The host asks the connector which authorization server protects it, at the standard discovery address/.well-known/oauth-protected-resource/mcp, and the answer names that authorization server. It then reads the authorization server’s own configuration document at /oauth/mcp/.well-known/openid-configuration. Both answers are public and neither needs a credential.
Do not configure an authorization server by hand. A host that follows the protocol finds it from those two documents.
List the tools
Once the connection is authorized, list tools and you receive the whole catalogue. Every tool carries its risk class as protocol metadata under the keycoffeechats/risk, with the value read, safe_write, consequential or browser_handoff, so the agent can tell a read from a write before it calls anything. The tool reference is generated from that same catalogue.
Make the first read
profile.get is the smallest honest first call. It takes no input:
profile.get input
Know the largest result before you ask for one
Every tool declares a maximum result size, and the connector measures the whole answer as it goes over the wire, wrapping JSON included. Most read tools are capped at 16,384 bytes. The six contact read tools are capped at 49,152, and the document reads and the apply batch list at 65,536, the largest budget in the catalogue. Limits lists every budget, and each tool’s own reference page prints its number. A result that would exceed its budget is never truncated. A tool whose single stored value can grow past the budget returns a measured fragment and a cursor instead, which the section below reassembles. Any other tool fails with the fixed textTool call failed. rather than sending a partial answer, which is why the reads are narrow and paged.
Page a list with a cursor
A list tool takes an optionalcursor and returns nextCursor beside its items. Send the value back unchanged on the next call to continue, and stop when nextCursor is null.
contacts.list input
Reassemble a value that arrives in fragments
Some tools read a single stored value that can be larger than the tool’s result budget. Rather than truncate it, the tool returns a measured fragment. Ask for one note:contacts.notes.get input
contacts.notes.get result
id names the value being fragmented, offset says where this chunk starts in it, and complete says whether this is the last one. The cursor is the same identifier and the next offset, encoded. Keep calling the same tool with nextCursor and concatenate every jsonChunk in the order received. The last answer sets complete to true and nextCursor to null:
contacts.notes.get result
jsonChunk is the whole document, and only then do you parse it as JSON. A note short enough to fit comes back in one answer of this second shape, with offset at zero.
A tool’s own reference page says whether it can return a fragment at all.
When a read fails
A read failure carries no code. It arrives as a protocol error holding one line of text, and that line is one of three. Almost every failure carries the fixed text:Protocol error envelope
contacts.get for an id the student does not have:
contacts.get input
A lookup that found no record of yours
contacts.list here, and work from the ids it returns. Failures that carry no code is the full rule, with the eight record kinds and the one further text a withheld transcript carries. Handle errors and retries covers the failures that do carry a code.
Next steps
Update a preference safely
The first write, with its replay and its conflict.
Limits and budgets
The call limits and the result size budgets these reads sit under.

