BetaFindAgent is in free public beta — every agent is free to connect and paid agents aren't available yet.
A manifest describes an agent; it never ships code. Here is the full anatomy, a working end-to-end example, and the checks the review pipeline runs before your listing goes live.
A declarative manifest can describe most REST APIs. It cannot describe an API that wants a secret in the request body, a computed signature, or a token exchange. Here's the full diagnostic.
Code agents are generated, not authored. The importer reads your DXT manifest, MCP config, .env.example, package.json and README — and everything runs in an ephemeral sandbox behind a default-deny allowlist.
There are exactly two ways an agent gets in front of a user.
Install puts it on their machine. The MCP client spawns a local process over stdio, the agent's credentials live in the local vault, and nothing leaves the laptop except the calls the agent makes.
Connect points the client at a hosted URL. Nothing runs locally; the gateway executes the agent and the client speaks to it over the remote transport.
Four manifest fields decide which of those happens, and they have to agree with each other:
| Field | What it answers |
|---|---|
kind |
What shape the agent is |
delivery |
Which transport carries it — prompt, mcp.stdio, mcp.remote |
exec |
Where it runs — user-local or findagent-hosted |
targets |
Which clients it supports |
Get the combination wrong and there's usually no error. The agent just never appears in the client.
flowchart TD
K{"kind?"}
K -->|"static-recipe"| P["delivery: prompt<br/>No transport at all.<br/>Pastes into every client. ✅"]
K -->|"skills-bundle"| S["delivery: mcp.stdio<br/>exec: user-local<br/>Skills served as MCP prompts"]
K -->|"code-bundle"| C["delivery: mcp.remote<br/>exec: findagent-hosted<br/>CONNECT-ONLY — never local ❗"]
K -->|"mcp-tool (doer)"| D{"Does targets<br/>include chatgpt?"}
D -->|"Yes"| R["delivery: mcp.remote<br/>exec: findagent-hosted<br/>ChatGPT has no local-doer path"]
D -->|"No"| L{"Where should<br/>it run?"}
L -->|"User's machine"| LS["delivery: mcp.stdio<br/>+ command / args<br/>exec: user-local"]
L -->|"Hosted"| R| Client | targets value |
Local install | Hosted connect | Notes |
|---|---|---|---|---|
| Claude Desktop | claude-desktop |
✅ | ✅ | Both paths fully supported |
| Claude Code | claude-code |
✅ | ✅ | CLI-driven install |
| ChatGPT | chatgpt |
❌ | ✅ | No local-doer path — hosted or recipe only |
| Cursor | cursor |
✅ | ✅ | |
| VS Code | vscode |
✅ | ✅ | |
| Gemini CLI | gemini-cli |
✅ | ✅ | |
| Windsurf | windsurf |
✅ | ✅ | |
| FindAgent CLI | cli |
✅ | ✅ | The install surface itself |
| Web | web |
— | ✅ | Runs in the browser against the gateway |
Keep targets to clients the agent has actually been used in. A long list is not a feature — it's a
list of places the agent might not work, and every one of them is a support ticket.
This is the single most common misconfiguration, so it's worth stating plainly:
If
targetsincludeschatgptand the agent has real tools,deliverymust bemcp.remote.
ChatGPT connects to MCP servers over a remote URL. It does not spawn local processes. So a doer
declared as mcp.stdio with chatgpt in its targets is describing something that cannot happen —
the listing shows ChatGPT support, the user tries to connect, and nothing works.
Two valid resolutions:
delivery: mcp.remote, exec: findagent-hosted. Works everywhere, including
ChatGPT.kind: static-recipe with
delivery: prompt pastes into ChatGPT and every other client with no transport at all.What isn't valid is keeping chatgpt in targets on a local doer because it looks better on the
card.
code-bundleis connect-only. Always hosted, never a local install.
Never emit mcp.stdio or exec: user-local for a code bundle. The whole point of the code path is
that submitted code runs in an isolated, ephemeral, per-run sandbox with a default-deny egress
allowlist — never on a buyer's machine. "Install this code agent locally" would mean shipping
arbitrary code to a user's laptop, which is precisely the thing the model exists to avoid.
Code bundles connect. That's the only path, and it's deliberate.
Recipes, local doers and skills bundles install through the CLI.
# install into a specific client
findagent install <agent-slug> --llm claude
# supply the credentials the manifest declared
findagent secrets set github_token ghp_xxxxxxxxxxxx
# verify
findagent list--llm accepts claude, chatgpt, gemini, cursor, custom. Note that this is a shorter
list than targets — the CLI's --llm flag names the config file it writes, while targets names
the runtime clients the agent supports. custom writes a generic MCP config block you paste
wherever you need it.
The ref in each credential slot is literally what the buyer types after secrets set. That's why
the guidance is short, stable, snake_case: github_token, not GitHub Personal Access Token v2.
For a local doer the manifest carries the process to spawn:
{
"kind": "mcp-tool",
"delivery": "mcp.stdio",
"exec": "user-local",
"command": "npx",
"args": ["-y", "@example/my-agent"],
"targets": ["claude-desktop", "claude-code", "cursor", "vscode", "cli"]
}No chatgpt in that list — deliberately, per the rule above.
Hosted doers and code bundles are connected, not installed. The gateway URL takes the form:
https://mcp.findagent.cloud/agents/<slug>
{
"kind": "mcp-tool",
"delivery": "mcp.remote",
"exec": "findagent-hosted",
"auth": "oauth-device",
"targets": ["claude-desktop", "claude-code", "chatgpt", "cursor", "vscode", "web"]
}auth here is FindAgent identity auth — how the client proves who it is to the gateway. It is
not the agent's external credentials, which are always the credential_slots. The two get conflated
constantly:
| Field | Answers | Values |
|---|---|---|
auth |
How does the client authenticate to FindAgent? | none, api-key, oauth-device |
credential_slots |
What secrets does the agent need for third-party APIs? | Slots with allowed_hosts |
On the connect path the buyer's credentials live in the platform vault and are attached per request by destination host. The agent never holds them, and neither does the client.
| Situation | Path | Why |
|---|---|---|
| Agent needs to read local files | Install | A hosted sandbox has no access to the user's disk |
| Agent must reach an internal network service | Install | The hosted runtime cannot route into a private network |
| Buyer must support ChatGPT | Connect | No local-doer path exists |
| Agent is a code bundle | Connect | Only path — always hosted |
| Buyer is non-technical | Connect | No CLI, no config file, no local runtime |
| Team of several people using one agent | Connect | One hosted agent beats N local installs to keep in sync |
| Prompt-only value | Recipe | delivery: prompt reaches everything with no transport |
A useful default: connect unless something forces local. The things that force local are real but specific — local filesystem access and private network reachability. Everything else is easier hosted, for you and for the buyer.
| Symptom | Cause | Fix |
|---|---|---|
| Agent never appears in ChatGPT | Local doer with chatgpt in targets |
delivery: mcp.remote, or ship as a recipe |
| Code bundle offered as a local install | mcp.stdio / exec: user-local on a code-bundle |
Connect-only, always hosted |
| Recipe won't paste into a client | delivery set to a transport |
static-recipe is always delivery: prompt |
| Installed agent starts but exposes no tools | command / args missing or wrong on an mcp.stdio doer |
Declare the process to spawn |
| Card advertises clients the agent fails in | targets padded beyond what was tested |
List only clients the agent actually supports |
| Client authenticates but tools 401 | auth confused with credential_slots |
auth is identity to FindAgent; API keys are slots |
findagent secrets set says unknown ref |
The ref typed doesn't match the manifest | Refs are exact, snake_case, case-sensitive |
kind, delivery, exec and targets mutually consistentstatic-recipe → delivery: promptmcp.stdio + command/args + exec: user-localmcp.remote + exec: findagent-hostedcode-bundle → never mcp.stdio, never exec: user-localchatgpt in targets on a local doertargets limited to clients actually supportedauth describes FindAgent identity, not third-party API keysrefs short, stable, snake_case — buyers type themllms (listing signal) and targets (runtime clients) both set deliberatelyWhat's the difference between installing and connecting an agent? Installing runs the agent on the user's machine, spawned by their MCP client over stdio. Connecting points the client at a hosted gateway URL, where the platform executes the agent — nothing runs locally.
Why can't I install a doer agent into ChatGPT?
ChatGPT connects to MCP servers over a remote URL and does not spawn local processes. A doer that
targets ChatGPT must use delivery: mcp.remote with exec: findagent-hosted, or ship as a prompt
recipe instead.
Can a code agent be installed locally? No. Code bundles are connect-only and always hosted. Submitted code runs in an isolated, ephemeral per-run sandbox with a default-deny egress allowlist, never on a buyer's machine.
What is the hosted gateway URL for an agent?
https://mcp.findagent.cloud/agents/<slug>, where the slug is the permanent identifier chosen at
the Basics step of submission.
What's the difference between auth and credential_slots?
auth is FindAgent identity authentication — how the client proves who it is to the gateway, using
none, api-key or oauth-device. credential_slots are the third-party API secrets the agent
needs, each bound to a destination host.
Should I install or connect by default? Connect, unless something forces local. Local install is required when the agent needs the user's filesystem or must reach a private network service; otherwise hosted is simpler for both creator and buyer.
Related: The MCP Agent Manifest Cookbook · Nine reasons a declarative agent becomes a code agent · Audience-bound credentials