Build a Production Strapi MCP Server for ChatGPT: Media & Content
Learn how to build a production-ready Strapi MCP server for ChatGPT to manage media and content, bypassing multipart/form-data hurdles and custom tool code.
If you need to connect Strapi to ChatGPT to manage the Media Library, publish content entries, or wire an AI agent into your editorial workflow, you need a Model Context Protocol (MCP) server sitting between the model and Strapi's REST API. The traditional approach of writing custom API wrappers, managing authentication state, and manually formatting LLM outputs into Strapi's specific JSON schemas is a massive engineering write-off. Instead, the industry has standardized on MCP to expose external APIs to AI agents reliably.
While the MCP standard defines a predictable JSON-RPC handshake, implementing it against Strapi's highly dynamic REST API presents significant hurdles. You have to handle complex relational data payloads, translate flat LLM tool calls into nested query parameters, and manage the notoriously difficult multipart/form-data requirements of the Strapi Media Library. Every time your content team adds a new collection type, your custom server code must be updated and redeployed.
This guide breaks down exactly how to architect a managed Strapi MCP server, bypass the pain of custom tool-calling infrastructure, handle the real API quirks that break naive integrations (especially around /api/upload), and connect it natively to ChatGPT's Developer Mode.
If you want the broader architectural view first, read our overview on Connect Strapi to ChatGPT: Manage Media, Content, and User Accounts. Teams on Claude should start with the Connect Strapi to Claude: Automate CMS Documents and Access Control guide instead.
TL;DR: Strapi's native MCP server exposes content types but explicitly cannot upload new media files, forcing you back to /api/upload with multipart/form-data. A managed MCP server handles that translation layer, plus token lifecycle, tool filtering, and rate-limit normalization, so ChatGPT gets clean tools and your team stops maintaining connector code.
Why Connect ChatGPT to Strapi via MCP?
The headless CMS market is compounding fast—industry reports project a 22.6% CAGR through 2036 for the segment, growing at roughly 2.4x the rate of traditional CMS platforms. That growth translates into more content types, more locales, more media assets, and a growing appetite for AI-driven editorial automation. As enterprises scale their content operations, automated content management via AI agents has shifted from a novelty to a hard requirement.
Historically, connecting ChatGPT to an external system required building custom OpenAI plugins or writing bespoke tool-calling scripts using the OpenAI SDK. These approaches were brittle. If the LLM hallucinated a parameter or failed to understand Strapi's specific pagination cursors, the integration broke silently.
MCP is the interface that made robust automation practical. ChatGPT's Developer Mode with MCP Server Tools support was officially announced on September 9th, 2025, letting ChatGPT interact with custom MCP servers over JSON-RPC 2.0. The legacy plugin model and hand-rolled function-calling shims are dead. If you want ChatGPT to draft an article, upload the hero image, set alt text, and publish—all in one conversation—MCP is the only sanctioned path.
A few architectural realities to internalize before writing any code:
- ChatGPT only accepts remote MCP servers. The server must be a public HTTPS endpoint speaking Server-Sent Events (SSE) or Streamable HTTP; ChatGPT cannot reach a server on your laptop or private network directly. Local
stdioservers are useless here. - Developer Mode is plan-gated. The Free tier gets no custom connectors; Plus and Pro get Developer Mode with custom MCP servers; Business, Enterprise, and Education tiers get it, but a workspace admin can switch it off or allowlist specific connectors.
- The MCP tool surface is what the model sees. Bad descriptions, sprawling schemas, or 50 half-relevant tools will tank tool-selection accuracy. Curation matters more than coverage.
- Client-Agnostic: An MCP server built for ChatGPT works equally well for Claude, Cursor, or any other MCP-compliant client. You build the integration layer once.
The Challenge of Strapi's Media Library API
Exposing basic text fields to an LLM is straightforward. Giving an LLM write access to an upload system is an entirely different engineering reality. Strapi's /api/upload endpoint is notoriously hostile to automated systems that expect standard JSON payloads. The endpoint has four major constraints that fight against how models naturally generate tool arguments.
1. Multipart/form-data vs. JSON-RPC
From the API perspective, you must send a multipart/form-data request to /api/upload with the actual file buffer, plus optional metadata for captions and alt text. However, JSON-RPC arguments are inherently flat JSON strings. LLMs do not natively construct multipart form boundaries, nor do they handle binary file streams. An MCP server has to translate the model's flat argument object into a multipart body, fetch the binary from a URL or base64 payload provided by the LLM, and stream it upstream to Strapi.
2. fileInfo Must Be a Stringified Object
This is the single most common footgun. Strapi's controller expects fileInfo (which contains alternative text, captions, and folder locations) as a strictly stringified JSON object inside the multipart body. Developers repeatedly hit errors like fileInfo must be an object, received null (a well-documented issue, such as GitHub Issue #23819) when clients pass the field the way a standard JSON API consumer would expect. The translation layer must intercept the nested JSON inside the form data and strictly stringify it before transmission, as LLMs almost never serialize this correctly on their first attempt.
3. Context-Window Pressure from Base64
If you route file bytes through the model as base64 strings, you burn tokens incredibly fast. Open-source Strapi MCP maintainers have had to add explicit guardrails: a 1MB base64 size limit with clear error messages about context overflow, response filtering to prevent echo overflow, and separate tools for handling file paths to avoid base64 context issues entirely. Anyone shipping this in production needs the same discipline to prevent a single image upload from exhausting the context window.
4. The Flat Input Namespace Problem
Beyond media uploads, Strapi relies heavily on nested query parameters for filtering, sorting, and populating relations. For example, fetching articles by a specific author requires a query like GET /api/articles?filters [author][name][$eq]=John. When an MCP client like ChatGPT calls a tool, all arguments arrive as a single flat object. The LLM has no concept of what belongs in the URL query string versus the HTTP request body. Your MCP server must parse this flat JSON-RPC arguments payload and correctly map each property to either the query schema or the body schema before forwarding the request to Strapi.
Self-Hosted vs. Managed MCP Servers for Strapi
You have three viable paths to expose Strapi to ChatGPT via MCP. Pick based on how much integration surface you want to own.
| Approach | What you own | What breaks first |
|---|---|---|
| Strapi's native MCP server (v5.49+) | Hosting, auth, TLS, upgrades, media upload workaround | Media uploads (not supported), multi-tenant token management |
| Roll your own custom MCP server | Everything: JSON-RPC transport, tool schemas, OAuth, rate-limit handling, deployment | Tool drift when content types change, upload payload correctness |
| Managed MCP (Truto) | Strapi credentials and which tools to expose | Nothing you have to page on at 2am |
Strapi recently introduced a native v5.49.0 MCP server. This is a massive step forward, positioning their platform as highly optimized for AI agents. However, it sidesteps the media upload problem by refusing to do it. Per the official docs, media fields accept existing media asset references, but the MCP server cannot upload new files. You must use Strapi's media library or upload API to add files first, then reference them in MCP tool calls. That defeats the point of a single conversational interface.
If you deploy a self-hosted custom MCP server, you own the infrastructure. You must host the Node.js process securely on the public internet, manage authentication state, and build a secure layer so random internet scanners cannot hit your MCP server URL. For teams building production-grade AI applications, maintaining this infrastructure quickly becomes a bottleneck. See our deep dive on this architectural burden: How to Build MCP Servers for AI Agents: 2026 Hands-On Architecture Guide.
The Managed Route (Truto) and Rate Limit Normalization
Managed unified API platforms like Truto eliminate the infrastructure burden. Instead of writing boilerplate mapping code, you authenticate Strapi once, and Truto dynamically generates a secure, hosted MCP server URL.
One critical detail that trips up teams evaluating managed platforms is how rate limits get handled. Truto does not magically absorb, silently retry, or swallow HTTP 429 errors from Strapi. Instead, when Strapi returns a 429, Truto passes the error directly to the caller and normalizes the upstream rate limit info into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset).
This means the ChatGPT-side client (or your agent runtime) owns the retry and exponential backoff logic, which is the correct architectural pattern for distributed systems. A platform that quietly swallows 429s hides real capacity problems and produces unpredictable end-to-end latency.
Step-by-Step: Building a Managed Strapi MCP Server with Truto
Instead of writing a custom Express server to handle JSON-RPC messages, you can generate a fully functional MCP server via the Truto API. This approach allows you to programmatically provision access for ChatGPT with strict boundaries.
Step 1: Connect the Strapi Integrated Account
In Truto, add Strapi as a connected integration and store the Strapi API token, base URL, and any custom content-type documentation. This becomes the integrated_account_id you'll reference below. If your Strapi instance runs behind a VPN or on a private subnet, expose it via a public HTTPS endpoint—ChatGPT cannot reach anything else.
Step 2: Generate the MCP Server via API
To create the server, you will make a POST request to Truto's API. You can configure specific filters to ensure ChatGPT only has access to the content types you explicitly allow.
curl -X POST https://api.truto.one/integrated-account/{integrated_account_id}/mcp \
-H "Authorization: Bearer YOUR_TRUTO_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Strapi - Editorial ChatGPT",
"config": {
"methods": ["read", "create", "update"],
"tags": ["articles", "media"],
"require_api_token_auth": true
},
"expires_at": "2026-09-30T23:59:59Z"
}'Step 3: Understand the Configuration Payload
The payload above utilizes several critical features for enterprise security and scope management:
- Tag-Based Tool Filtering (
tags): By passing["articles", "media"], the resulting MCP server will entirely ignore endpoints related to users, webhooks, or admin settings. The LLM simply will not know those endpoints exist. Truto applies this filter at the documentation-fetching stage, ensuring zero tool leakage. - Method Filtering (
methods): Filters the tool set by operation type.readcoversgetandlist;writecoverscreate,update, anddelete. Excludingdeletealone is a common safety choice for an editorial agent. - Built-in Expiry (
expires_at): Sets a strict Time-To-Live (TTL). Once this ISO datetime is reached, the underlying token is destroyed automatically, and the MCP server URL instantly returns a 401 Unauthorized. Great for contractor access or short-lived automated workflows. - Extra Authentication (
require_api_token_auth): By default, an MCP URL is accessible to anyone who possesses it. Setting this totrueadds a second layer of security, requiring the client to pass a valid Truto API token in theAuthorizationheader to execute tools. Use this for any URL that might end up in logs or shared workspaces.
Step 4: Understand What Tools ChatGPT Will See
Tools are generated dynamically on every tools/list request based on your specific Strapi environment's schema. They are never cached or stale. For each Strapi resource with documentation, tool names come out as descriptive snake_case strings:
list_all_strapi_articlesget_single_strapi_article_by_idcreate_a_strapi_articleupdate_a_strapi_article_by_idlist_all_strapi_mediacreate_a_strapi_media(This is the tool that solves the multipart/form-data problem)
Query schemas get limit and next_cursor auto-injected for list methods, with an explicit instruction to pass cursors back unchanged. This is the fix for LLMs that love to "clean up" opaque pagination tokens.
Configuring ChatGPT to Use Your Strapi MCP Server
Once Truto returns your unique MCP server URL (e.g., https://api.truto.one/mcp/a1b2c3d4e5f6), wiring it into ChatGPT takes about two minutes.
- Enable Developer Mode: In ChatGPT on the web or desktop app, navigate to Settings > Apps > Advanced settings and toggle Developer mode to the ON position. (Note: On Business and Enterprise workspaces, an admin may need to allow it first via Workspace Settings > Permissions & Roles > Connected Data > Create custom MCP connectors).
- Create the Connector: Scroll down to MCP servers / Custom connectors and click to add a new server. Enter a descriptive name, such as "Strapi Production CMS", and a description that helps the model decide when to use it (e.g., "Manage Strapi articles and media library. Use for CMS reads, drafting posts, uploading images, and setting alt text."). Paste the Truto MCP URL into the Server URL field.
- Handle Authentication: If you generated the server with
require_api_token_auth: true, you must add your Truto API token as a Bearer credential in the connector's auth settings. ChatGPT sends it on every request; Truto's middleware will validate it before it ever reaches the tool execution layer. - Scan Tools and Publish: ChatGPT enumerates the tools it discovered. Toggle off any you don't want. Because tools are generated dynamically, editing documentation or adding a content type takes effect immediately upstream, but ChatGPT caches the tool list per connector. Hit Refresh in the connector settings to pull new definitions when your Strapi schema changes.
Architecture Flow
When ChatGPT invokes a tool, the request follows a strict, stateless path, handling the complex translation seamlessly.
sequenceDiagram
participant User as Editor in ChatGPT
participant GPT as ChatGPT Client
participant Truto as Truto MCP Router
participant Strapi as Strapi API
User->>GPT: "Draft article, upload hero image, publish"
GPT->>Truto: POST /mcp/{token} (JSON-RPC tools/list)
Truto-->>GPT: Filtered tools schema (articles, media)
GPT->>Truto: POST /mcp/{token} (JSON-RPC tools/call create_a_strapi_media)
Note over GPT,Truto: Payload contains flat JSON arguments
Truto->>Truto: Validate token & translate to multipart/form-data
Truto->>Strapi: HTTP POST /api/upload (Binary + stringified fileInfo)
Strapi-->>Truto: 200 OK { id, url }
Truto-->>GPT: JSON-RPC Result (Formatted for LLM)
GPT->>Truto: POST /mcp/{token} (JSON-RPC tools/call create_a_strapi_article)
Truto->>Truto: Split arguments into Query & Body schemas
Truto->>Strapi: HTTP POST /api/articles (Mapped Payload)
Strapi-->>Truto: 201 Created (Article Data)
Truto-->>GPT: JSON-RPC Result
GPT-->>User: "Published with hero image #482"Executing Content and Media Workflows
With the connection established, ChatGPT now has semantic understanding of your Strapi schema. Because Truto dynamically generated the tools based on your environment, ChatGPT knows exactly which fields are required for an Article and how to format the request. You can execute complex, multi-step workflows using natural language.
Here are a few prompts that map directly to the tools exposed:
Example Prompt 1: Media Upload and Management
"Upload the image at https://cdn.example.com/q3-launch.jpg to Strapi, set the alt text to 'Q3 Product Launch Hero Graphic' to improve our SEO accessibility, and return the file ID."
ChatGPT will call the create_a_strapi_media tool. Truto intercepts the flat arguments, fetches the image, constructs the multipart/form-data request, ensures the fileInfo payload is correctly stringified, and executes the POST request to Strapi.
Example Prompt 2: Content Generation and Publishing
"Draft a 500-word blog post about the benefits of headless CMS architectures. Once written, use the Strapi tool to create a new Article entry. Set the title to 'The Future of Headless', set the status to 'draft', assign it to the 'engineering' category, and attach media ID 482 as the hero image."
ChatGPT will draft the content, format the JSON arguments, and call the create_a_strapi_article tool with the media relation set. Truto handles the translation of the flat namespace into Strapi's expected body schema.
Example Prompt 3: Bulk SEO Audits
"List the 10 most recent articles missing SEO meta descriptions and propose one for each."
This triggers a list_all_strapi_articles call with cursor pagination, followed by multiple update_a_strapi_article_by_id calls. The tools operate against Strapi's native resource shapes, meaning the model can use Strapi's native filter operators ($contains, $in, $gte) directly without fighting a normalization layer.
The Reality of LLM Orchestration
While MCP provides the perfect bridge between the LLM and the API, you must still write defensive prompts. LLMs can and will make assumptions about your data model if you do not provide explicit instructions. Always instruct the model to verify data via a list or get method before executing a create or update method.
If the model encounters a rate limit (HTTP 429), it will receive the standardized ratelimit-reset header in the tool response. You must explicitly prompt the agent to read this header and wait the specified duration before retrying the operation, as the underlying infrastructure will not automatically back off on its behalf.
Where to Take This Next
If you're piloting AI editorial workflows, start narrow: deploy one MCP server, expose one content type, allow read and create methods only, and set a seven-day TTL. Measure how often the model picks the right tool and how often it formats payloads correctly. Widen the scope only after tool selection accuracy is above 90% on your test prompts.
By leveraging a managed MCP platform, you remove the operational burden of maintaining integration infrastructure, allowing your engineering team to focus on building better agentic workflows rather than debugging multipart form data payloads and JSON-RPC transport layers. For teams standardizing on MCP across multiple SaaS surfaces, the same pattern extends to CRMs, ticketing systems, and internal APIs. The What is an MCP Server? The 2026 Architecture Guide for SaaS PMs guide covers the multi-tenant patterns worth adopting early.
FAQ
- Can ChatGPT connect to a local Strapi MCP server?
- No. ChatGPT's Developer Mode only accepts remote MCP servers reachable over public HTTPS via Streamable HTTP or SSE. A local `stdio` MCP server or a Strapi instance on your laptop won't work—you need either a hosted Strapi with a public MCP endpoint or a managed MCP URL from a platform like Truto.
- Why is Strapi's Media Library difficult for AI agents to use?
- Strapi's `/api/upload` endpoint requires multipart/form-data requests and strictly stringified JSON metadata for the `fileInfo` field. LLMs generate flat JSON strings natively, making it difficult for them to construct the correct file payloads without a translation layer.
- Does Strapi's official native MCP server support media uploads?
- No. Strapi's official native MCP server (v5.49+) sidesteps media uploads. The official documentation recommends uploading files first via the REST API or admin panel, then referencing the returned media ID in MCP tool calls.
- How does Truto handle Strapi rate limits when ChatGPT calls the MCP server?
- Truto does not retry or apply backoff on rate limit errors. When Strapi returns an HTTP 429 error, Truto passes the error through to the caller and normalizes rate-limit metadata into standard IETF headers (`ratelimit-limit`, `ratelimit-remaining`, `ratelimit-reset`). Retry and backoff logic is the client's responsibility.
- Can I restrict which Strapi content types ChatGPT can access?
- Yes. When creating a managed MCP server via the API, you can use the `config.tags` array to include only the resources you want exposed (e.g., `["articles", "media"]`). Combined with `config.methods` for operation-type filtering, you can produce a tightly scoped tool list before ChatGPT ever sees it.