Beyond MCP · Beyond MCP — OpenAPI, Custom GPTs, citation
GPT Actions vs MCP — different discovery topology, same goal
Hook
You shipped MCP. Cursor finds you, Claude Desktop finds you, Claude Code finds you. ChatGPT users still can't reach your tool. The fix is not a second MCP server — it's a different topology.
Concept
Prerequisites: a public HTTP endpoint, a working sense of what .well-known/mcp.json does, the ability to read an OpenAPI 3.x fragment, and m3 l1 (Rate-limit OAuth /register for AI clients) behind you. This lesson covers the mental shift between two ways an AI agent learns your tool exists, and the single artifact that serves both.
Two doors, opposite directions
MCP is the front door with a sign. The agent walks up, reads .well-known/mcp.json, finds the endpoint, queries the schema, and starts calling operations — no human in the loop. Server-mediated discovery.
GPT Actions is the front door with a guest list. ChatGPT does not crawl for tools. A human opens the GPT builder, pastes your OpenAPI URL into the Actions panel, clicks deploy, and only then does the agent learn your address. User-mediated attachment.
Same goal. Opposite paths to the door. Ship only one and you reach half the agent population.
One artifact, two consumers
A single OpenAPI 3.x spec at a public URL covers both. The MCP server wraps it for the agent-mediated path. The Custom GPT imports it for the user-mediated path. Build the spec once; both ecosystems read it. That is the entire architectural shift. Everything below is mechanics.
Walk-through
You already have the OpenAPI URL — the same spec your MCP server exposes (in this project it lives at workers/rag.js's /openapi.json route). The Custom GPT side has four moves.
- Open the GPT builder at
https://chatgpt.com/gpts/editor→ Configure → Actions → Import from URL. - Paste the OpenAPI URL. ChatGPT validates the schema and lists every operation it found.
- Pick the auth mode:
- None — read-only public reads.
- API Key in headers — do not use this for user-scoped data. The GPT creator's key gets reused across every conversation, so user A's data leaks into user B's session.
- OAuth 2.0 — the right answer for anything user-scoped.
- Before testing OAuth, allowlist
https://chat.openai.comin your OAuth provider. Custom GPT OAuth flows redirect tohttps://chat.openai.com/aip/g-<gpt-id>/oauth/callback. If your allowlist is locked to your own domain, the first user's auth attempt fails withredirect_uri_mismatch— the failure is invisible from your side; the user sees a generic OpenAI error page. (Redirect URI pattern current as of 2026-05-07; verify againstplatform.openai.com/docs/actionsbefore shipping.)
Set the GPT to Public if directory discovery matters — ChatGPT's GPT store is search-indexed — or Private for invite-only. Same citation hygiene as MCP: if your endpoint returns url fields in its JSON, the GPT cites the source. Without them, ChatGPT summarizes without attribution.
If you get stuck
redirect_uri_mismatchon the first OAuth round-trip. You forgot to allowlisthttps://chat.openai.com. Add it (or the specific callback path) to your OAuth provider's redirect list and retry.- The Custom GPT works for the creator but fails for every other user. You picked API Key in headers. The creator's key is the only key the GPT carries. Switch the auth mode to OAuth and re-import.
- ChatGPT can't see your tool at import time. The OpenAPI URL is behind auth, returns the wrong content-type, or 404s for unauthenticated requests. Curl it from a private window; you should get
application/json(orapplication/yaml) at a public URL with no auth required.
Cross-reference
m3 l1 (Rate-limit OAuth /register for AI clients) applies to both surfaces — every endpoint either ecosystem touches needs the same calibration, because ChatGPT user traffic shares the same egress-IP shape as Claude.ai.
Deliverable
You have a Custom GPT in the ChatGPT builder that imports your existing OpenAPI URL, with OAuth configured (or none if read-only), https://chat.openai.com on the OAuth allowlist, and at least one operation tested end-to-end with a real user account. You can say without checking notes: MCP is server-mediated discovery, GPT Actions is user-mediated attachment, and the OpenAPI spec is the one artifact that serves both.
Further reading
- "Closing the Agent Discovery Loop" — the framing for why AI agent discovery differs from human discovery, and the shape your public surface needs to take.
Try these prompts
- Explain in three sentences why a single OpenAPI 3.x spec at a public URL covers both an MCP server and a ChatGPT Custom GPT Action, and which two consumers read it differently.
- Walk through the exact failure mode when a Custom GPT's OAuth flow first redirects a user, given the GPT redirect URI pattern, and name the one allowlist change that fixes it.
- Compare GPT Actions' three auth modes (none, API key in headers, OAuth 2.0) for a tool that returns user-scoped data, and explain why API key in headers is brittle in that case.
Sign in to keep your place and tick off lessons. Reading stays open either way.