Repository navigation
feat: make the plugin submittable to the OpenAI directory - #12
Merged
Merged
Conversation
The plugin detail page shows the checkly MCP server as "Not connected" with Connect, Reconnect and Rescan all disabled, so the submission can't proceed. OpenAI reads a server's OAuth settings from `extensions["com.openai"].auth`, which the repo's .mcp.json never declares - so the portal has no auth configuration to connect with. Add that block inside the submission ZIP the same way the manifest name is already swapped, leaving the repo file alone for marketplace installs. The rewrite is additive only, because the portal rejects two things we tried first: `$schema` is invalid: Extra inputs are not permitted. Adding, removing, or replacing an MCP server isn't supported for existing plugins. The second one fires when `type` moves to the Agent Plugins transport name `streamable-http`, so the transport, URL and scopes stay as the repo declares them.
Two additions to the OAuth block in the submission ZIP. `client.mode: "cimd"` gives the portal a registration method. The repo declared none, DCR is unavailable on auth.checklyhq.com (no registration_endpoint) and a `provided` client would need a client ID we don't have. A Client Identifier Metadata Document needs no registration at all, and a connector created with it completed OAuth against the tenant, so it demonstrably works. `defaultScopes: []` stops the fallback. ChatGPT's connection form shows default scopes pre-selected to all 17 scopes the server advertises, including checkly:environment-variables:write, and documents that they are requested in addition to the base scopes. Without the override the scope narrowing from c3042bd is undone at connect time and the two environment variable tools OpenAI flagged come back.
The ZIP replaced the manifest `name` with app-6a7f1be5a9e48191b23a7b6ae73cf976 on the belief that the directory pins the name to an existing listing ID and rejects anything else. The portal's own API contradicts that: the plugin record reports can_edit_package_name true and app_id null, and its identifier is plugins_6ae9d4ac3ddc81919bedf3fef36760da, assigned on creation. The name we were sending is just echoed back as the package name. The hex came from asdk_app_6a7f1be5a9e48191b23a7b6ae73cf976, a ChatGPT app reference added in 57dbc8e and reverted in 131b6c4, re-prefixed and reused as a package name. Ship `checkly` instead, as the repo manifest declares it. The .app.json stripping and the OpenAI auth block are unaffected.
The listing uploaded from the compatibility layout came back with transport "http" and no app attached, and the portal's own diagnostic says apps are created "for the first supported remote MCP in a new plugin upload". `http` isn't a transport the Agent Plugins schema knows - it allows stdio, streamable-http and sse - so the compatibility manifest validated while very likely not registering as a supported remote MCP. Build the ZIP as the documented portable package instead: a root plugin.json carrying portable identity plus extensions["com.openai"], and a root mcp.json declaring streamable-http with the OAuth block. Both are generated from the repo's compatibility manifests, which stay as they are for marketplace installs. This also resolves the earlier "`$schema` is invalid" rejection: that was the compatibility .mcp.json, which is validated against a closed model. The portable mcp.json is specified to carry $schema.
The portal's review wizard shows test cases as read-only: "Review test cases are managed by your plugin ZIP". It wants exactly five positive cases and exactly three negative ones, so they live in the manifest under extensions["com.openai"].review and travel with the package. The positive cases cover the flows the listing advertises - check status, inspecting a failing result, creating an API check, running a check on demand, and root cause analysis - and name the tools the scan actually discovered. The negative cases are the documented limitations: environment variable writes, Playwright Check Suites, and billing. toPortableManifest now merges the manifest's own extensions["com.openai"] with the interface it moves there, so review and publication reach the portable plugin.json. demo_recording_url is left out: there's no recording yet, and the portal accepts the walkthrough URL and release notes directly.
The demo account reviewers use has a check called Login, so the prompt names it instead of a 'homepage browser check' that doesn't exist there.
Case 2 now asks about the account's API checks, and case 5 names the Products API check instead of a checkout check that doesn't exist there. Case 2's expected behaviour follows the plural prompt.
api.example.com has no DNS record, so a check created against it would error instead of demonstrating the non-200 assertion. example.com is reserved for documentation and answers 200.
"Deploy the Playwright Check Suite in this repository to Checkly" isn't a case where the plugin should stay out: the bundled checkly skill lists Playwright Check Suites among the things it handles, and its generic `checkly api` pass-through covers most account operations besides. Comparing the server's tool list against the scan confirms only create-account-environment-variable and update-account-environment-variable are withheld from the plugin, so a negative case can't rest on a missing tool. Use an action outside monitoring instead: rolling back a deploy follows naturally from the plugin reporting failing checks, which is exactly where a mistaken trigger would happen.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gets the Checkly plugin to the point where it can be submitted to the OpenAI plugin directory, and adds the review material the submission form asks for.
Why the previous submission was stuck
The earlier listing showed its MCP server as "Not connected" with Connect, Reconnect and Rescan all disabled, and no error anywhere in the UI. The dashboard API explained it:
No app was attached, so there was nothing for those buttons to act on — and apps are only attached on the first upload of a new plugin, which is why no amount of re-uploading fixed it. The package it was created from used the Codex compatibility layout with
"type": "http", which isn't a transport the Agent Plugins schema knows (stdio,streamable-http,sse).A fresh plugin created from the portable package in this PR attached an app immediately, connected over OAuth, and scanned 46 tools.
What changed
Packaging (
scripts/package.ts) — the ZIP is now a portable Agent Plugins bundle: rootplugin.jsonandmcp.jsongenerated from the repo's compatibility manifests, withskills/,assets/,LICENSEandREADME.md. The compatibility manifests and.app.jsonare no longer shipped. The repo's own files are untouched, so Claude Code, Cursor and Codex marketplace installs are unaffected.mcp.jsondeclaresstreamable-http, andextensions["com.openai"].authwithclient.mode: "cimd",baseScopesanddefaultScopes: [].plugin.jsonkeeps portable identity at the root and movesinterfaceunderextensions["com.openai"].checklyagain; theapp-6a7f1be5…override is gone. That value was a ChatGPT app ID reused as a package name, and the dashboard reportscan_edit_package_name: truewith its ownplugins_…identifier.CIMD instead of a registered OAuth client —
auth.checklyhq.comadvertises noregistration_endpoint, so DCR isn't available. A Client Identifier Metadata Document works and needs no client registration: the authorize request goes out withclient_id=https://chatgpt.com/oauth/client.jsonand PKCE. No Auth0 work needed.defaultScopes: []— this is the one with teeth. ChatGPT's connection form defaults to requesting every scope the server advertises, includingcheckly:environment-variables:write. Without the override, the scope narrowing from c3042bd was undone at connect time and the two environment-variable tools OpenAI flagged came back. With it, the authorize request carries exactly our 14 scopes, and the tool scan shows onlylist-account-environment-variablesandget-account-environment-variable.Review material (
.codex-plugin/plugin.json) — the submission form shows test cases read-only ("managed by your plugin ZIP"), so five positive and three negative cases live in the manifest underextensions["com.openai"].review, along withcommerceand release notes. The positive prompts name checks that exist in the review demo account.On the negative test cases
A negative case here can't rest on "the MCP server has no tool for it". Diffing the server's advertised tools against the scan shows only two are withheld from the plugin:
Everything else is exposed, and the
checklyskill's genericcheckly apipass-through covers most account operations besides. So the three negatives are:CHECKLY_API_KEYas an account environment variable. The only case grounded in a withheld tool, and it answers the October rejection about tools accepting raw secret values.checklyskill lists Playwright Check Suites among the things it handles, so the plugin should engage with that prompt rather than stay out.Incidentally,
get-error-group-root-cause-analysesis exposed even though the package never requestscheckly:error-groups:read; the server gates it onrca:read. Positive case 5 depends on that tool, so it's worth knowing the scope list doesn't need widening for it.Not in this PR
Reviewer credentials, the demo walkthrough URL and country availability are portal-side and already filled in the dashboard. Still outstanding before submission:
readOnlyHint/openWorldHint/destructiveHintwith a justification on every tool, which has to come from the MCP server itself.