BBotnexio

Buy now!

← All guides

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 / descriptionTool description (and optional title)
Parameters + request body schemainputSchema (JSON Schema)
Response schemaOptional outputSchema + structuredContent
Action auth (API key / OAuth)Server-side key, or OAuth 2.1 per the MCP authorization spec
Hosted at your API URLMCP 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: true only when the tool cannot change state.
  • destructiveHint: true when the outcome is irreversible or hard to reverse.
  • openWorldHint: true when the tool reaches the public internet or open-ended external entities. A bounded private account can be false.

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 zod

A 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 Origin header and answer an invalid one with 403. That's your allowlist.
  • Running locally, bind to 127.0.0.1, not 0.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:

  1. 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.
  2. 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 with S256, and the resource parameter 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.
  • [ ] inputSchema is explicit; nothing relies on the model guessing IDs.
  • [ ] Results return stable IDs and no secrets.
  • [ ] The endpoint is public HTTPS, Streamable HTTP, typically /mcp.
  • [ ] Origin is 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

All checked October 16, 2026.