Files
pad/cmd
xarmian 26fd8a6a46 feat(mcp): ChatGPT tools declare their OAuth scope; a missing scope answers the sign-in challenge (TASK-3321 U2c) (#1720)
* feat(mcp): ChatGPT tools declare their OAuth scope; a missing scope answers the sign-in challenge (TASK-3321 U2c)

Every ChatGPT catalog tool now carries securitySchemes, an oauth2 scheme
naming the one scope it needs: pad:read for a read tool and pad:write for
anything else. The Apps SDK reads it at the tool's top level and keeps
_meta.securitySchemes as a mirror. mcp-go's Tool marshals a fixed set of
keys, so the tool carries the _meta copy, and WithChatGPTToolSchemes adds
the top-level copy to a single tools/list JSON response on the ChatGPT
mount. Every other request and response passes through byte for byte.

When a write tool is called with a read-only grant, the handler answers
before dispatching anything: an isError result whose
_meta["mcp/www_authenticate"] is a Bearer challenge with
error="insufficient_scope" and an error_description, naming the
protected-resource document of the mount the request arrived on
(server.MCPResourceMetadataURLFromContext). That is what makes ChatGPT
offer to reconnect with the wider grant. The wire golden is built through
the production transport (newChatGPTTransport). Only the ChatGPT golden
moved; /mcp is byte-identical. ChatGPTToolSurfaceVersion stays 0.1: it is
unstable and unpublished.

Claude-Session: https://claude.ai/code/session_01H63zaWhkb5pAafx2WGjrVC

* test(mcp): ChatGPT tools/list is a JSON body with top-level securitySchemes when asked the way ChatGPT asks (TASK-3321 U2c)

Streamable HTTP upgrades a response to an event stream only by flushing
notifications mid-request (the remote transport has no event store), and
WithChatGPTToolSchemes hands the transport a writer that cannot flush. So
tools/list requested with Accept: application/json, text/event-stream is a
JSON body, and every tool carries securitySchemes at the top level. One leg
pins that through the production transport, and another pins that the
buffered writer never implements http.Flusher.

Claude-Session: https://claude.ai/code/session_01H63zaWhkb5pAafx2WGjrVC
2026-10-02 04:37:12 -04:00
..