Goal
List docs.plus in the OpenAI Plugin Directory, so any ChatGPT user can find it and add it in one click.
We build no new server. A ChatGPT plugin is a plugin.json package that points at the MCP connector we already run (https://prodback.docs.plus/api/mcp). OpenAI reviews the package once. Then the plugin appears in the directory, on every plan and on mobile.
What exists today
Old ChatGPT plugins (ai-plugin.json) closed in 2024. Nothing from them applies. The current format is the 2026 Plugin Directory package described below.
Before you start (agents)
- Read
AGENTS.md, then apps/hocuspocus.server/CLAUDE.md §MCP Connector.
- Bun only. Never run
npm, npx, yarn or pnpm.
- Do not commit, push or open a PR unless the maintainer asks.
- Do not add a password sign-in path. Do not bring back passkeys. Do not add a tool that replaces a whole section or page. These are maintainer rulings in
CLAUDE.md and apps/hocuspocus.server/CLAUDE.md §MCP Connector.
- Never write reviewer credentials into the repo, an issue, or a commit. They go only into the OpenAI dashboard form.
- Do not claim audience binding anywhere. Supabase always sets
aud to authenticated. The token's client_id claim is the gate.
Rulings needed (maintainer)
Rule R2 and R3 before the first submission. After publication, a hint change waits for OpenAI's daily scan, and the old hint stays live until then.
R1. How does the OpenAI reviewer sign in?
The Submit page wants a reviewer account that works "without MFA approval, email or SMS codes, magic links, or private-network access". docs.plus signs in with Google or an email link only. That rules out the email link.
| Option |
Fits OpenAI |
Fits docs.plus rules |
| A. A dedicated Google account with 2-Step Verification off |
Yes, unless Google challenges a new device |
Yes. No code |
| B. A password account, or a separate reviewer login route |
Yes |
No. It overturns the rule "Never add a password sign-in path" |
| C. A separate review server |
No. A listing has one MCP URL |
n/a |
Recommendation: A. Test it the way a reviewer would. Use a fresh browser on a desktop, on a network other than the maintainer's usual one. If Google shows a device challenge, A fails, and the maintainer must rule on B.
R2. openWorldHint on the five read tools
Today all five read tools set false. OpenAI says to use true for "public or open-ended entities", and that connectivity alone does not decide it. find_documents with scope: "public" searches anyone's public documents. The other four read tools can open those documents too.
Recommendation: true on all five.
R3. destructiveHint on post_chat_message
Today it is false. OpenAI uses true for irreversible sends, and says undo alone does not justify false. A post can notify members who are away, and a notification cannot be recalled.
Recommendation: true. ChatGPT then asks the person to confirm before a post that other people will see.
create_document notifies no users. append_to_document, edit_blocks and replace_text produce batched digest notices to followers through the normal save path. That is the same path a person's edit takes, so this issue changes nothing for them.
Work plan
Each step has an owner: M (maintainer), C (code agent), O (ops).
Step 0. Ship what is built
Done when ChatGPT lists edit_blocks and replace_text, and all three live calls pass.
Step 1. Prove the connector in ChatGPT
Done when every tool has run once in ChatGPT, and the plan's write limit is known.
Step 2. Code work (C)
Start only after the #329 fix is on main. Until then, main still has replace_section, and these files do not match this issue.
Tool hints (after R2 and R3). No test asserts a hint today. typecheck is the only automated check.
Plugin package.
Package skeleton (only 1 positive and 1 negative case shown; the full set is below):
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "docs-plus",
"version": "1.0.0",
"description": "Find, read, create and edit your docs.plus documents and their heading chats.",
"extensions": {
"com.openai": {
"interface": {
"displayName": "docs.plus",
"shortDescription": "Read and edit your documents",
"longDescription": "<at most 4000 characters>",
"developerName": "<must match the verified OpenAI identity>",
"category": "Productivity",
"websiteURL": "https://docs.plus",
"supportURL": "https://github.com/docs-plus/docs.plus/issues",
"privacyPolicyURL": "https://docs.plus/privacy",
"termsOfServiceURL": "https://docs.plus/terms",
"defaultPrompt": ["Find my docs.plus document called Launch plan and show me its outline."],
"logo": "./assets/logo.png"
},
"review": {
"test_cases": {
"positive": [
{
"description": "Find a document and show its outline",
"prompt": "Find my docs.plus document called Launch plan and show me its outline.",
"tools_triggered": "find_documents, get_outline",
"expected_behavior": "Shows the heading tree of Launch plan."
}
],
"negative": [
{ "description": "No document is needed", "prompt": "Write a short poem about autumn." }
]
},
"demo_recording_url": "<public video URL>"
},
"publication": { "release_notes": "First release." }
}
}
}
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"docs-plus": { "type": "streamable-http", "url": "https://prodback.docs.plus/api/mcp" }
}
}
Field rules from the Submit page:
name: at most 64 characters. Lowercase letters, numbers and single hyphens.
displayName and shortDescription: at most 30 characters each. longDescription: at most 4000. developerName: at most 80.
- The display name must not add "MCP" or "Plugin". Do not list it as "docs.plus for ChatGPT", because that can read as an OpenAI endorsement.
tools_triggered is one string, not an array.
defaultPrompt: up to 3, at most 128 characters each, with no @ mentions.
- Leave out
screenshots. That field is only for plugins that return UI.
- Leave out
publication.countries on the first upload.
Review test cases. The first review needs exactly 5 positive and 3 negative cases. These are drafts for the maintainer to approve. They assume the reviewer account owns a Launch plan document with Budget, Risks and Timeline headings. The Timeline body holds the text Q3 exactly once. The Timeline chat room holds a few messages.
| # |
Prompt |
tools_triggered |
| P1 |
Find my docs.plus document called Launch plan and show me its outline. |
find_documents, get_outline |
| P2 |
Summarize the Risks section of my Launch plan document. |
find_documents, read_document |
| P3 |
Create a docs.plus document called Meeting notes with the headings Agenda and Actions. |
create_document |
| P4 |
In Launch plan, change "Q3" to "Q4" in the Timeline section, and add a short risk at the end of Risks. |
find_documents, read_document, replace_text, edit_blocks |
| P5 |
What did people say in the Timeline chat of Launch plan? |
find_documents, list_chat_rooms, read_chat_thread |
| N1 |
Write a short poem about autumn. |
none |
| N2 |
What is the capital of France? |
none |
| N3 |
Open my Google Doc called Budget. |
none |
Domain token.
Privacy page.
Before a public listing.
Checks for code agents:
cd apps/hocuspocus.server && env -u REDIS_HOST bun test src/modules/mcp src/modules/document-content/__tests__/unit
bun run --filter @docs.plus/hocuspocus typecheck
Step 3. Account work (M)
Done when the dashboard shows no open finding before Submit for review.
Step 4. Submit and review (M)
After publication, OpenAI scans the server daily. A new tool stays unavailable until it is approved. A change to metadata or assets needs a new ZIP and a new review. A change to the MCP URL needs OpenAI support.
Out of scope
Acceptance
Open questions
| Question |
How to settle it |
| Can Plus and Pro call write tools in developer mode? |
One write call on the maintainer's plan (Step 1) |
| Does Google challenge a fresh device for an account with 2-Step Verification off? |
A live test from a fresh browser, on a network other than the maintainer's usual one |
| Does Google sign-in work in the ChatGPT mobile OAuth sheet? |
Probably not testable before publication. Mention it in the review notes |
Does OpenAI accept docs.plus as the parent domain of prodback.docs.plus? |
The dashboard's domain check |
Does hosted Supabase Auth advertise CIMD or RFC 9207 iss? Local Auth does not, so ChatGPT uses DCR and a per-connector redirect URI, which works today |
Read the hosted discovery document |
| What do OpenAI's brand rules allow for "Add to ChatGPT" wording? |
Open https://openai.com/brand/ in a browser before changing Settings copy |
References
Goal
List docs.plus in the OpenAI Plugin Directory, so any ChatGPT user can find it and add it in one click.
We build no new server. A ChatGPT plugin is a
plugin.jsonpackage that points at the MCP connector we already run (https://prodback.docs.plus/api/mcp). OpenAI reviews the package once. Then the plugin appears in the directory, on every plan and on mobile.What exists today
docs/mcp/README.md.title,readOnlyHint,destructiveHintandopenWorldHint.Old ChatGPT plugins (
ai-plugin.json) closed in 2024. Nothing from them applies. The current format is the 2026 Plugin Directory package described below.Before you start (agents)
AGENTS.md, thenapps/hocuspocus.server/CLAUDE.md§MCP Connector.npm,npx,yarnorpnpm.CLAUDE.mdandapps/hocuspocus.server/CLAUDE.md§MCP Connector.audtoauthenticated. The token'sclient_idclaim is the gate.Rulings needed (maintainer)
Rule R2 and R3 before the first submission. After publication, a hint change waits for OpenAI's daily scan, and the old hint stays live until then.
R1. How does the OpenAI reviewer sign in?
The Submit page wants a reviewer account that works "without MFA approval, email or SMS codes, magic links, or private-network access". docs.plus signs in with Google or an email link only. That rules out the email link.
Recommendation: A. Test it the way a reviewer would. Use a fresh browser on a desktop, on a network other than the maintainer's usual one. If Google shows a device challenge, A fails, and the maintainer must rule on B.
R2.
openWorldHinton the five read toolsToday all five read tools set
false. OpenAI says to usetruefor "public or open-ended entities", and that connectivity alone does not decide it.find_documentswithscope: "public"searches anyone's public documents. The other four read tools can open those documents too.Recommendation:
trueon all five.R3.
destructiveHintonpost_chat_messageToday it is
false. OpenAI usestruefor irreversible sends, and says undo alone does not justifyfalse. A post can notify members who are away, and a notification cannot be recalled.Recommendation:
true. ChatGPT then asks the person to confirm before a post that other people will see.create_documentnotifies no users.append_to_document,edit_blocksandreplace_textproduce batched digest notices to followers through the normal save path. That is the same path a person's edit takes, so this issue changes nothing for them.Work plan
Each step has an owner: M (maintainer), C (code agent), O (ops).
Step 0. Ship what is built
main(positioned edits:edit_blocksandreplace_textreplacereplace_section).replace_sectionwhen the directory review starts.create_document, onereplace_textand oneedit_blockson a scratch document.Done when ChatGPT lists
edit_blocksandreplace_text, and all three live calls pass.Step 1. Prove the connector in ChatGPT
<!-- PENDING-HOST-TEST: ChatGPT -->marker indocs/mcp/README.md(§Connect in ChatGPT) when it passes.Done when every tool has run once in ChatGPT, and the plan's write limit is known.
Step 2. Code work (C)
Start only after the #329 fix is on
main. Until then,mainstill hasreplace_section, and these files do not match this issue.Tool hints (after R2 and R3). No test asserts a hint today.
typecheckis the only automated check.apps/hocuspocus.server/src/modules/mcp/tools/documentTools.ts:openWorldHintonfind_documents,get_outlineandread_document.apps/hocuspocus.server/src/modules/mcp/tools/chatTools.ts:openWorldHintonlist_chat_roomsandread_chat_thread. SetdestructiveHintonpost_chat_message, and rewrite the comment above it ("A post only adds…").docs/mcp/reference.md: the hints prose, the Hints column, and thepost_chat_messagenote.apps/hocuspocus.server/API.md: the tool table and the Hints. paragraph.apps/hocuspocus.server/CHANGELOG.md: the Tool hints follow the MCP and OpenAI definitions. paragraph under## [Unreleased]. It is not published yet, so edit it in place.Plugin package.
integrations/openai-plugin/withplugin.json,mcp.jsonandassets/logo.png. The folder sits outside the workspace globs and outsidedocs/. Add nopackage.json.apps/webapp/public/icons/icon-192x192.png. Do not use amaskable_*icon.appsfield, a.app.jsonfile, lifecycle hooks,test_credentialsorreviewer_instructions. OpenAI refuses a package that has any of them. Plugin Creator output contains.app.json, so do not submit it as it is.bun run checkonce, to confirm the lint and format gates accept the new JSON. If Prettier fails, runbun run format:fix, then check again.Package skeleton (only 1 positive and 1 negative case shown; the full set is below):
{ "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "docs-plus", "version": "1.0.0", "description": "Find, read, create and edit your docs.plus documents and their heading chats.", "extensions": { "com.openai": { "interface": { "displayName": "docs.plus", "shortDescription": "Read and edit your documents", "longDescription": "<at most 4000 characters>", "developerName": "<must match the verified OpenAI identity>", "category": "Productivity", "websiteURL": "https://docs.plus", "supportURL": "https://github.com/docs-plus/docs.plus/issues", "privacyPolicyURL": "https://docs.plus/privacy", "termsOfServiceURL": "https://docs.plus/terms", "defaultPrompt": ["Find my docs.plus document called Launch plan and show me its outline."], "logo": "./assets/logo.png" }, "review": { "test_cases": { "positive": [ { "description": "Find a document and show its outline", "prompt": "Find my docs.plus document called Launch plan and show me its outline.", "tools_triggered": "find_documents, get_outline", "expected_behavior": "Shows the heading tree of Launch plan." } ], "negative": [ { "description": "No document is needed", "prompt": "Write a short poem about autumn." } ] }, "demo_recording_url": "<public video URL>" }, "publication": { "release_notes": "First release." } } } }{ "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json", "mcpServers": { "docs-plus": { "type": "streamable-http", "url": "https://prodback.docs.plus/api/mcp" } } }Field rules from the Submit page:
name: at most 64 characters. Lowercase letters, numbers and single hyphens.displayNameandshortDescription: at most 30 characters each.longDescription: at most 4000.developerName: at most 80.tools_triggeredis one string, not an array.defaultPrompt: up to 3, at most 128 characters each, with no@mentions.screenshots. That field is only for plugins that return UI.publication.countrieson the first upload.Review test cases. The first review needs exactly 5 positive and 3 negative cases. These are drafts for the maintainer to approve. They assume the reviewer account owns a
Launch plandocument withBudget,RisksandTimelineheadings. TheTimelinebody holds the textQ3exactly once. TheTimelinechat room holds a few messages.tools_triggeredfind_documents, get_outlinefind_documents, read_documentcreate_documentfind_documents, read_document, replace_text, edit_blocksfind_documents, list_chat_rooms, read_chat_threadDomain token.
apps/webapp/public/.well-known/openai-apps-challenge.apps/webapp/public/.well-known/security.txtis the precedent.apps/webapp/src/proxy.tsalready skips.well-known, so do not edit it. A(build): frontdeploy then serves the file athttps://docs.plus/.well-known/openai-apps-challenge.text/plain. If Next sends another type, add a header inapps/webapp/next.config.jsheaders(), as/robots.txtdoes.Privacy page.
apps/webapp/src/pages/privacy.tsx. The page already says a connected app gets name, profile picture and email, and never a phone number.Before a public listing.
/api/mcp. C builds it after the ruling. The global limiter inapps/hocuspocus.server/src/middleware/index.tsruns before the MCP router. It keys on the client IP over 15 minutes. ChatGPT calls come from OpenAI's servers, not from each person's device. The per-person tool budget lives inapps/hocuspocus.server/src/modules/mcp/infra/toolBudget.ts. Do not key the global limiter on a token before the token is verified.get_outlineandlist_chat_rooms). OpenAI does not list it as a review blocker. A public listing brings more callers, so the caps matter more.Checks for code agents:
Step 3. Account work (M)
api.apps.writeon the Review page).Q4back toQ3, and remove the added risk.integrations/openai-plugin/for upload. Check the root layout against Package your plugin.Done when the dashboard shows no open finding before Submit for review.
Step 4. Submit and review (M)
https://platform.openai.com/plugins. Run the tool scan. Enter reviewer credentials in the dashboard form only.docs/mcp/README.md. Add it to Settings > Connected apps (apps/webapp/src/components/settings/components/ConnectedAppsSection.tsx) after the brand-rules open question is settled.After publication, OpenAI scans the server daily. A new tool stays unavailable until it is approved. A change to metadata or assets needs a new ZIP and a new review. A change to the MCP URL needs OpenAI support.
Out of scope
Acceptance
Open questions
docs.plusas the parent domain ofprodback.docs.plus?iss? Local Auth does not, so ChatGPT uses DCR and a per-connector redirect URI, which works todayReferences