OpenAPI to MCP Server: Rebuild Your GPT Action as MCP Tools
Your custom GPT calls an API through a GPT Action. That action won't survive the move to plugins. The good news: the OpenAPI spec you wrote for it is a solid starting point for an MCP server.
This guide shows how to map each operation to an MCP tool, when a converter helps, and what to check before you connect.
Why actions need rebuilding
OpenAI's migration FAQ is direct: "GPT custom actions do not transfer through the migration workflow." Features that depend on them stop working in the plugin until you set up a replacement, and "rebuilding the connection may require a custom MCP server and technical setup."
The deadline: custom GPTs are scheduled to retire on Dec 11, 2026 (according to OpenAI, subject to change). Enterprise workspaces with an approved deferral have until Feb 11, 2027.
OpenAI's own advice in Replacing a GPT custom action: rebuild the connection as a new plugin and reuse the existing API where possible. Before you migrate, save the action schema, the authentication method and the non-secret connection settings from the GPT editor's Actions section.
GPT Actions vs MCP: concept mapping
| GPT Action (OpenAPI) | MCP |
|---|---|
One operation (operationId) | One tool (name) |
summary / description | Tool description (and optional title) |
| Parameters + request body schema | inputSchema (JSON Schema) |
| Response schema | Optional outputSchema + structuredContent |
| Action auth (API key / OAuth) | Server-side key, or OAuth 2.1 per the MCP authorization spec |
| Hosted at your API URL | MCP endpoint over Streamable HTTP, typically /mcp |
The biggest shift is mindset. OpenAI's tool guide says: "Do not mirror an internal API without considering how people will ask for and use the capability."
Map each operation: a worksheet approach
Make a table with one row per OpenAPI operation. For each row, fill in the fields OpenAI's Define tools page lists: name, title, description, input schema, output schema, authorization, side effects and failure behavior. Then decide: keep, merge, split or drop.
Tool names and descriptions
The MCP tools spec says tool names SHOULD:
- be 1–128 characters long,
- use only ASCII letters, digits,
_,-and., - contain no spaces or commas,
- be unique within the server (and are treated as case-sensitive).
getUser, DATA_EXPORT_v2 and admin.tools.list are the spec's own valid examples.
For descriptions, describe the user's intent, not your implementation. Say what the tool does, when to use it, and how it differs from similar tools.
Read vs write tools
Split reads from writes. OpenAI suggests patterns like list_projects, get_project, create_project, update_project and archive_project rather than one tool with many modes.
Then set the annotations to match real behavior:
readOnlyHint: trueonly when the tool cannot change state.destructiveHint: truewhen the outcome is irreversible or hard to reverse.openWorldHint: truewhen the tool reaches the public internet or open-ended external entities. A bounded private account can befalse.
Annotations help ChatGPT pick confirmation behavior. They don't replace authorization or validation on your server. The MCP spec also tells clients to treat annotations as untrusted unless the server is trusted.
Cut endpoints you don't need
Admin routes, internal health checks and bulk exports rarely belong in a chat tool. Every extra tool is something the model can pick by mistake. If a use case doesn't need it, drop it.
Converters and generators vs. hand-written tools
The OpenAI guides linked here don't describe an OpenAPI-to-MCP converter; they build tools by hand. Third-party tools exist. A common Python option is FastMCP:
import httpx2
from fastmcp import FastMCP
client = httpx2.AsyncClient(base_url="https://api.example.com")
openapi_spec = httpx2.get("https://api.example.com/openapi.json").json()
mcp = FastMCP.from_openapi(
openapi_spec=openapi_spec,
client=client,
name="My API Server",
)
if __name__ == "__main__":
mcp.run()(Example from the FastMCP docs.) By default FastMCP turns every endpoint into a tool. You can exclude routes with RouteMap(..., mcp_type=MCPType.EXCLUDE) and rename tools with mcp_names.
FastMCP is candid about the trade-off: LLMs "achieve significantly better performance with well-designed and curated MCP servers than with auto-converted OpenAPI servers", especially for complex APIs. Its docs recommend generation for bootstrapping and prototyping, not for mirroring your API.
Rule of thumb: use a generator to get a prototype running in an hour, then hand-write the handful of tools you actually keep.
Minimal TypeScript server over Streamable HTTP
OpenAI's Build an MCP server guide uses the official TypeScript SDK (@modelcontextprotocol/sdk) with zod:
npm install @modelcontextprotocol/sdk zodA server with one read-only tool, adapted from that guide:
const server = new McpServer({ name: "acme-projects", version: "1.0.0" });
server.registerTool(
"list_projects",
{
title: "List projects",
description: "Use this when the user wants to find or review projects in their Acme workspace.",
inputSchema: { status: z.enum(["active", "archived"]).optional() },
annotations: { readOnlyHint: true, openWorldHint: false, destructiveHint: false },
},
async ({ status }) => {
const projects = await listProjects({ status }); // your existing API call
return {
structuredContent: { projects },
content: [{ type: "text", text: `Found ${projects.length} projects.` }],
};
}
);Then expose it over Streamable HTTP. Per the MCP transport spec (2026-07-28):
- One MCP endpoint that accepts POST, e.g.
https://example.com/mcp. - The server MUST validate the
Originheader and answer an invalid one with 403. That's your allowlist. - Running locally, bind to
127.0.0.1, not0.0.0.0.
Follow your SDK version's README for the exact transport wiring. Then check the server with MCP Inspector (npx @modelcontextprotocol/inspector), choose Streamable HTTP and enter http://localhost:3000/mcp.
Auth: where the backend key lives
Two separate questions:
- How your MCP server talks to your API. Keep the API key on the server, e.g. in your host's secret manager. Never in tool results, descriptions or chat. OpenAI says to keep secrets and access tokens out of tool metadata and results.
- How ChatGPT users sign in to your MCP server. For user-specific data or write actions, OpenAI expects OAuth 2.1 per the MCP authorization spec: protected resource metadata at
/.well-known/oauth-protected-resource, PKCE withS256, and theresourceparameter echoed into the token audience. Your server verifies every token itself. OpenAI strongly recommends an established identity provider over building auth from scratch.
ChatGPT can't send custom API keys to your MCP server, and it doesn't support machine-to-machine grants such as client credentials. The full setup is in OpenAI's Authentication guide.
Checklist before you connect
- [ ] Every kept tool maps to a real user goal.
- [ ] Names follow the MCP naming rules and are unique.
- [ ] Reads and writes are separate tools with accurate annotations.
- [ ]
inputSchemais explicit; nothing relies on the model guessing IDs. - [ ] Results return stable IDs and no secrets.
- [ ] The endpoint is public HTTPS, Streamable HTTP, typically
/mcp. - [ ]
Originis validated. - [ ] Every tool call passes MCP Inspector with valid and invalid inputs.
- [ ] Your ChatGPT plan supports custom MCP servers: ChatGPT Plus is not supported, Pro is read-only, full support on Business, Enterprise and Edu (as of Oct 16, 2026, subject to change; OpenAI Help).
For the migration as a whole (instructions, knowledge files, testing), see How to migrate a custom GPT to a ChatGPT plugin.
Want a starting point?
The Aramac MCP Server Starter Kit (TypeScript) is a template for your own MCP server on the official @modelcontextprotocol/sdk. According to the product page it includes Streamable HTTP and stdio transports in one codebase, example tools with zod schemas, three auth modes (none, API key, OAuth 2.1 resource server) and a Dockerfile. Requirements: Node.js 22.12 or newer. Not included: hosting, custom development or app-directory submission. €39 incl. VAT, sold by Aramac GmbH. Already have an OpenAPI spec from a custom GPT? The GPT-to-Plugin Kit (€19 incl. VAT) covers that side.
Connecting your server to ChatGPT? Follow our step-by-step guide (German): Connect an MCP server to ChatGPT.
FAQ
Do GPT Actions transfer to ChatGPT plugins?
No. According to OpenAI's migration FAQ, GPT custom actions do not transfer through the migration workflow. You rebuild the connection, typically as a custom MCP server, and can reuse the existing API.
Is there an official OpenAPI to MCP converter?
OpenAI's plugin docs don't describe one; they define tools by hand. Third-party tools such as FastMCP can generate an MCP server from an OpenAPI spec. FastMCP itself recommends this for prototyping and says curated tools work better.
What is the difference between GPT Actions and MCP?
A GPT Action describes your API as OpenAPI operations for one GPT. MCP is an open protocol where a server exposes named tools with JSON Schema inputs, which ChatGPT, Codex and other clients can call.
How should I name MCP tools?
The MCP spec says names should be 1 to 128 characters, use only ASCII letters, digits, underscore, hyphen and dot, and be unique within the server. Use action-oriented names like get_project.
Can I use my MCP server with ChatGPT Plus?
Custom MCP servers are not supported on ChatGPT Plus. Pro can connect them read-only. Full support is on Business, Enterprise and Edu (as of Oct 16, 2026, subject to change).
Sources
- OpenAI Help: Custom GPT retirement and migration FAQ
- OpenAI Help: Connecting custom MCP servers in ChatGPT
- OpenAI: Model Context Protocol (Replacing a GPT custom action)
- OpenAI Plugins: Build an MCP server, Define tools, Authentication
- MCP specification 2026-07-28: Tools, Streamable HTTP
- FastMCP (third party): OpenAPI integration
All checked October 16, 2026.