app-submit: one manifest for every agent store
app-submit checks an MCP tool against each store's published submission rules. Then it submits the listing where a store has a safe path, and reads the review status.
You write one app-submit.json with the package, the listing text, the MCP server URL, the tool hints and the review test cases. Each store reads the fields it needs from that one file, so the name, the descriptions and the URLs never drift between stores.
Stores
Each store has an adapter, and each adapter says how it submits. An api adapter calls a real HTTP endpoint. A browser adapter drives the store's web form in a signed-in browser. A manual adapter prints the exact steps and every value to paste, because the store has no safe automatic path.
| Store | Id | Kind | Sign-in |
|---|---|---|---|
| ChatGPT plugin directory | chatgpt | api | An OpenAI key with api.apps.write, or a signed-in browser |
| Official MCP registry | mcp-registry | api | A GitHub token, or an Ed25519 key proved by DNS or HTTP |
| Smithery | smithery | api | A Smithery API key for a namespace you own |
| Glama | glama | manual | A Glama account |
| PulseMCP | pulsemcp | manual | None: it copies the official MCP registry |
| mcp.so | mcp-so | manual | A GitHub account |
| Claude connector directory | claude | manual | A paid claude.ai plan |
| Meta Muse connectors | muse | browser | A Meta account in an ego-browser task space |
| Vercel Connect | vercel-connect | manual | A Vercel team; the server must use OAuth |
| Uneed launch directory | uneed | api | A token from an emailed 6-digit code |
Every rule has an id, a severity (error or warn) and a link to the store guideline it comes from. A failure says what to fix and where the rule is written.
Quick start
app-submit init my-tool --name my-tool # writes my-tool/app-submit.json
app-submit validate my-tool # offline rules for every store
app-submit validate my-tool --live # also calls the MCP server and every public URL
app-submit submit chatgpt my-tool --dry # shows what would be sent
app-submit submit chatgpt my-tool # uploads a draft, never a review request
app-submit status all my-tool # listing and review state in every store
Every command prints one JSON object on stdout and nothing else, so an agent can read the result without parsing text. Without --full, validate shows only the failed and warned rules.
Exit codes
| Code | Meaning |
|---|---|
0 | ok |
1 | a rule failed, or a store answered with a failure |
2 | usage: a bad argument, a missing manifest or a missing consent flag |
3 | the store refused the request: sign-in or permission |
4 | network: the store could not be reached |
5 | internal error |
With all in place of a store id, the exit code is the highest one among the stores.
MCP server mode
app-submit-mcp speaks MCP over stdio. Its tools are list_stores, validate_manifest, import_submission_json, init_manifest, build_package, submit_listing and review_status, and each result is in structuredContent.
{ "mcpServers": { "app-submit": { "command": "app-submit-mcp" } } }
What it never does
It never sends a listing to a store review on its own. ChatGPT review needs both --for-review and --accept-terms, because the second flag accepts the submission terms for the owner. In a browser form it never ticks a consent box and never selects Submit. A store whose rules fail is skipped unless you pass --force.
Keys come from environment variables only. app-submit never prints them and never writes them to its state file, which holds only the ids each store assigned.
Get it
app-submit needs Node 22 and has no other dependencies. The source lives in packages/app-submit of the Agent Tools repository and is not on npm yet. After a clone, npm link puts app-submit and app-submit-mcp on your PATH. To list a tool from this catalog, see the MCP install guides.