deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

ChatGPT app directory rejection for MCP server traced to metadata and reviewer login

A dev.to postmortem describes a month-long path to list an MCP server in ChatGPT's app directory: the server barely changed, but tool discovery, scanner metadata and a usable reviewer login made the difference.

ChatGPT app directory rejection for MCP server traced to metadata and reviewer login

A month-long review for a server that barely changed

According to a first-person account on dev.to by Eugeniya Ivanova, what looked like a formality — listing an already-working MCP server in ChatGPT's app directory — turned into a month-long process that ended in a rejection on August 24 and approval on September 4. The striking part: almost none of the fixes touched the server's actual functionality. The work went into how ChatGPT discovers tools, what OpenAI's scanner expects, how the app was described, and whether a reviewer could physically log in.

Tool discovery has to work before authentication

The first problem appeared before submission. When the server was connected, ChatGPT created the connector but reported that no actions were available, even though the same tools loaded without issue in Claude and Cursor. Caching and SSE were investigated and ruled out. The real cause: the server required a token for the tools/list request itself. Claude authenticates first and fetches the list afterwards, which is why it worked there. ChatGPT fetches the list before authorization, receives an empty result, and the app then locks up — with refresh disabled and save greyed out — leaving deletion and re-creation as the only way out. Ivanova's new pre-flight rule: tools/list must return a 200 with the tools present and no token.

The scanner wants annotations the spec leaves optional

OpenAI's scanner examined every tool and required explicit values for readOnlyHint, openWorldHint and destructiveHint. Four read-only tools lacked destructiveHint, which is defensible under the MCP spec, since that hint only matters when readOnlyHint is false. The scanner wanted it regardless, so the team added destructiveHint: false and wrote justifications for roughly forty annotation values. The tools themselves did not change.

A domain check with format quirks

Domain verification expects the endpoint to return a bare token string — no JSON wrapper, no quotation marks. It is also not a one-time check: the endpoint has to stay in production, responding identically afterwards. The team now maintains a small endpoint whose permanent job is returning that string whenever OpenAI asks.

Description drift was a real bug, just not in the server

One finding was genuinely the team's own. The public repo defined 18 tools while the live server exposed 16, and four LinkedIn analytics tools present in the repo were not exposed over MCP at all. Because the app description was based on the repo, it advertised analytics that MCP users could not actually reach. Ivanova removed them from the description and release notes, then found the same stale text in the README of a Zed extension and in an open PR for the Docker MCP Catalog — the Zed PR referenced a pre-correction commit, so merging it would have carried the outdated claim into another catalog.

The rejection came down to the reviewer's login

The app was submitted on August 5 with every wizard step completed in one pass, and rejected on August 24 with a message citing an inability to complete the sign-in or OAuth flow and asking for valid credentials that required no additional setup or verification. Retesting showed nothing broken: dynamic client registration returned 201, /authorize reached the consent screen, the sign-in page was a plain email-and-password form without a captcha, unauthenticated tools/list returned the tools, and API and MCP access were enabled on every plan including the free tier.

The actual issue was the account handed to the reviewer. The team's own accounts used Google sign-in, with the second factor landing on their phones — credentials a stranger had no way to use. Two earlier Canva rejections had failed for the same reason, which the author admits should have been a signal.

What finally got it approved

The team created a dedicated reviewer account with email-and-password login, confirmed ahead of time, with channels connected and some posts and drafts already in place. They also supplied eight test cases, five positive and three negative. The most useful was a full write-path test through a fake publishing target that validates posts against the same rules as a real one, returns the same kind of response, and discards the request instead of publishing anywhere — roughly thirty lines of code. Ivanova notes most of these fixes were written with Claude's assistance while she checked and decided what changed. The resubmission went in the evening of August 24; approval arrived September 4.

Why it matters

MCP is quickly becoming a distribution channel, and ChatGPT's directory applies app-store-style review on top of the protocol spec. This account shows that passing review depends less on protocol correctness than on client-specific behavior: discovery before authentication, scanner-enforced metadata that goes beyond the spec, exacting verification formats, and a reviewer experience that works for someone who is not you. It also illustrates a quieter operational risk: as a product's descriptions spread across repos, extension READMEs and catalog submissions, they drift from what the product actually exposes — and reviewers will notice. Ivanova's summary checklist for next time is simple: walk through the product as the reviewer would, not as yourself.

  • #mcp
  • #chatgpt
  • #openai
  • #app-review
  • #oauth

Related posts