Everything a Gateway offers
The one page an agent reads to make the most of a Gateway for a person: apps, MCP apps and the compact MCP surface, people and their roles, groups, caps and Activity from the Admin UI, a terminal or an AI client, Cloudflare Access, every CLI verb by job, what to suggest next, and which other MCP servers to recommend.
A Gateway is one Worker (every-app-gateway) with one D1 database (every-app-gateway) in the person's own Cloudflare account, at https://<gateway host>, installed by pnpm everyapp setup --domain <host>. It signs people in, decides who may open which app, holds every key, and serves one MCP connector for every app. This page says what it offers and how an agent reads each part; the deeper pages are linked, not repeated.
The shape
- The Gateway. The sign-in, the app launcher, Manage workspace (
/admin, owners and admins) and the connectorhttps://<gateway>/mcp. Its state is the D1 database; the CLI reads and writes that database through the Cloudflare login, never through the Gateway (ADR-0003,docs/security-model.md).pnpm everyapp status --jsonis the one state query (the CLI by job). - Apps. Each app is a Worker of its own on a host under the app base domain (
<app>.<base>), built from itseveryapp.config.ts(manifest) bypnpm everyapp deployfrom the app's directory, or bypnpm everyapp install <GitHub URL>from a release someone published (deploy). An app lives beside the checkout in a repository of its own, linked to it (the CLI by job). The Gateway gives an app only what its manifest declares: a signed identity, its ownsecrets, AI throughproviders, services throughcapabilities(identity, secrets). Every route is private unless the manifest lists it underpublic, which only a route the internet must reach needs (a webhook, a collector, an OAuth callback); the starter has none. An app's AI tools aredefineTools()in its code, snapshotted by the Gateway and served as<app>_<tool>(mcp). An agent writes one with the build skill (Build an app, Example patterns). - MCP apps. A data provider, or any remote MCP server, the Gateway offers to members' AI clients as an app with no page and no Worker (a provider app in the code: an
appsrow of tierprovider,PROVIDER_APP_TIER), turned on bypnpm everyapp mcp on <id>or added bypnpm everyapp mcp add <url>, its key or credential a Gateway setting. The registry isPROVIDER_APPSinpackages/sdk/src/internal/providerApps.ts; the ids arePROVIDER_APP_IDS, todaydataforseoalone (keyDATAFORSEO_API_KEY; seventeen read tools inapps/every-app-gateway/src/server/provider-apps/dataforseo.ts, listed in full on/mcpasdataforseo_<tool>); a remote server is a row whose manifest carries aremoteblock (packages/perimeter/src/registry/remoteMcpApps.ts), its tools served throughpackages/toolbus/src/remote/. To a person, a card under "MCP apps" on the launcher with a "Use it from your agent" dialog (this Gateway's MCP address, the tool prefix); its row in Apps, its calls in Usage and Activity. Reference: mcp;docs/design/2026-10-mcp-apps-ui.md(section 3, every person-facing surface),docs/design/2026-10-mcp-provider-apps.md,docs/design/2026-10-mcp-by-url.md. - The one connector.
https://<gateway>/mcpserves every app the caller can use plus the built-ins named under the reserved app ideveryapp(packages/toolbus/src/builtins.ts): five core ones,everyapp_list_apps,everyapp_whoami,everyapp_search_tools,everyapp_call_readandeveryapp_call_write, and the workspace tools (packages/toolbus/src/workspace.ts): every action of Manage workspace aseveryapp_workspace_<action>for an owner or admin, four every member has over their own tokens and AI connections (People), and the MCP app tools (packages/toolbus/src/mcpApps.ts, owners and admins):everyapp_mcp_list,everyapp_mcp_show,everyapp_mcp_add,everyapp_mcp_remove,everyapp_mcp_on,everyapp_mcp_off,everyapp_mcp_refreshandeveryapp_mcp_tool, themcpcommands' twins; and the provider tools (packages/toolbus/src/providers.ts):everyapp_provider_listandeveryapp_provider_connectionsfor every member,everyapp_provider_disconnectfor a member's own account (an owner's or admin's for anyone's),everyapp_provider_addandeveryapp_provider_removefor owners and admins on a self-hosted Gateway, theprovidercommands' twins (the provider tools); and the sign-in provider tools (packages/toolbus/src/signin.ts, owners and admins):everyapp_signin_listandeveryapp_signin_show, the reads of Sign-in, with no tool that adds or removes a provider (the sign-in provider tools). Behind the Gateway's OAuth and consent page, or a personal access tokenepat_…; every call audited as onemcp_tool_callsrow. An app host serves its ownhttps://<app-host>/mcponly where its manifest opts in (mcp: { by, why }, manifest): that one app, to a personal token, with no OAuth; none of the four open apps does. A member connects once and every app they can open follows (Connecting clients).
Apps, MCP apps and the compact surface
| An app | An MCP app | The compact surface | |
|---|---|---|---|
| What it is | A Worker on the person's account with a page, a database and tools: an apps row with a hostname |
A data provider's curated tools (DataForSEO, built in) or any remote MCP server added by its URL, as an app of the Gateway's own: an apps row of tier provider with no hostname and no Worker, served in-process by the Gateway, which alone holds the credential |
Not an app: how /mcp lists tools when the full list would be too long. The core built-ins under the id everyapp |
| Who deploys or turns it on | The person's agent: pnpm everyapp deploy from the app's directory, or pnpm everyapp install <URL>; pnpm everyapp delete <id> removes it |
The operator: pnpm everyapp mcp on dataforseo, or pnpm everyapp mcp add <url> for a remote server (--name <id>; --auth bearer, header, basic, oauth or none; --secret <NAME>); pnpm everyapp mcp off <id> leaves a tombstone like a deleted app and pnpm everyapp mcp remove <id> drops the row with everyone's access; pnpm everyapp mcp list (alias mcp ls) says which are on |
The Gateway, per connection: compact past FULL_LISTING_MAX_TOOLS (256) or FULL_LISTING_MAX_BYTES (1 MiB), else full; or the caller's choice by the header X-EveryApp-Tools (full or compact) or ?tools= on the URL |
| Where its tools come from | defineTools() in the app, snapshotted on activation and on each deploy |
The Gateway's own curated set over the provider's REST API, through the capability proxy with the Gateway's key; a remote server's own tool list, snapshotted and listed again within the hour or on pnpm everyapp mcp refresh <id>; pnpm everyapp mcp show <id> prints every tool with its risk, and pnpm everyapp mcp tool <id> <tool> --risk read (or write, destructive, annotations) or --off overrides one |
packages/toolbus/src/builtins.ts; everyapp_search_tools finds app and workspace tools, everyapp_call_read and everyapp_call_write run one each |
Name on /mcp |
<app>_<tool> |
<id>_<tool>: dataforseo_keyword_overview, dataforseo_serp_google, …; a remote server's tool names normalized to that shape (packages/toolbus/src/remote/normalize.ts) |
everyapp_<tool> |
| Listed | In full mode every tool, after everyapp_list_apps, everyapp_whoami, everyapp_search_tools and the workspace tools the caller's role reaches; in compact mode none, each found by everyapp_search_tools and callable by name or through a wrapper (unlisted is not hidden) |
The same | full: the three read-only built-ins and the workspace tools, the wrappers callable but unlisted; compact: the five core built-ins (everyapp_call_write only for a read & write caller), the workspace tools unlisted but found and run like an app's |
| Who can use it | Members granted the app (Apps → Manage access), or every member when Available to everyone is on (is_default; the first deploy sets it from the manifest's access: admins, the default, or everyone) |
The person who turned it on, owners and admins; others granted in Apps → Manage access | Every caller of the connector |
| Setup state | A required secret, provider or capability unset: Needs setup on the Gateway, tools out of /mcp, available: false with a reason in everyapp_list_apps; pnpm everyapp configure <app> sets up everything it declares |
The key unset: the same Needs setup, mcp list says not set; pnpm everyapp secret set DATAFORSEO_API_KEY (the setup file packages/cli/skills/everyapp/setup/dataforseo.md); a remote server's credential is the Gateway setting <ID>_MCP_TOKEN, pinned to the server's origin (mcp add --from-env <VAR> sets it at once; the setup file packages/cli/skills/everyapp/setup/remote-mcp.md) |
Always on |
The instructions a client reads at initialize (gatewayInstructionsHead, packages/toolbus/src/view.ts) name the mode, the apps, and each app that needs setup with its command, under CLAUDE_CODE_INSTRUCTIONS_READ (4,096 characters). An agent on /mcp calls everyapp_list_apps first, and everyapp_whoami for the person's role or the connection's access.
People
Roles are owner, admin and member (apps/every-app-gateway/src/server/org-roles.ts; the action-by-role table is in docs/design/2026-10-teams.md). A member opens the apps they are given and connects AI clients; an admin also invites, manages apps and groups, deletes a user or an app, sets caps and reads Usage and Activity; an owner can also make or demote another owner and remove one (owners are peers; the workspace always keeps one; only an owner acts on an owner). The identity an app receives carries org_role; everyapp_whoami answers user.role.
Everything below is Manage workspace (/admin, the sidebar footer's link; apps/every-app-gateway/src/routes/_app/admin.tsx), for owners and admins; a member who opens it sees "You don't have access to this page". The terminal and the connector do the same, tab by tab, below. The person's page is /docs/people. Every command and every tool, paired with the UI action each stands for, is on Managing the workspace: the CLI and the MCP tools.
| Tab | What it does |
|---|---|
Users /admin/users |
Invite user: an email and a role, member or admin, never owner; by email when the Gateway has a sender, else Invite link, single use, 72 hours. Change a role, Password reset link (an hour; passwords on), Deactivate user (signed out everywhere; their tokens and AI connections stop working), Reactivate user, Delete user (owner; deactivates instead when Cloudflare Access would let them straight back in). A Gateway is invite-only. |
Sign-in /admin/sign-in |
The ways people sign in beside their password (apps/every-app-gateway/src/server/sign-in-providers.ts, the catalog packages/sdk/src/internal/signInProviders.ts): Password on or off (EMAIL_PASSWORD_SIGN_IN), Cloudflare Access when its sign-in is on, then Continue with Google, Microsoft, GitHub, Apple, Cloudflare and SSO (an OIDC issuer), each On, Needs setup (some of its settings are set; it stays off, and the row says what is missing) or Off with Set up. The dialog shows the OAuth app to make at the provider, the redirect URL to register (https://<gateway>/api/auth/callback/<id>, with a copy button), each setting <ID>_SIGNIN_<FIELD> with whether it is set (never a value), the command pnpm everyapp signin add <id> and the skill's setup/signin-<id>.md. Read-only: the settings are Worker secrets set from a terminal (pnpm everyapp signin add, list, show and remove), never from the UI or a tool, so a stolen admin session can't add a way in. |
Apps /admin/apps |
Every app and MCP app with who deployed it and who can open it. ⋯ → Manage access grants people one by one (user_app_access); Edit app → Available to everyone (is_default); name and description; Delete app (owners and admins). After the first deploy the CLI changes none of this; a redeploy never changes access. |
Groups /admin/groups |
A named set of members with app grants (groups, group_members, group_app_access; grp_ ids): give a team the same apps at once. Access-only: a group is never a cap or a policy. |
Tokens /admin/tokens |
Personal access tokens: New token, a name, all my apps or one app, an expiry (90 days by default). The token epat_… is shown once; Authorization: Bearer epat_… on /mcp is read & write. Each person sees their own; an admin cannot list another member's. |
Providers /admin/providers |
Every provider the Gateway brokers (the catalog's and the rows registered with pnpm everyapp provider add; docs/design/2026-10-oauth-providers.md): kind, source, whether its key or client is set and bound, connections. Add OAuth provider picks a preset (the catalog's Google, Microsoft, Slack and Discord clients marked built in; GitHub, Notion, Linear, GitLab, Atlassian, HubSpot, Zoom, Dropbox, Spotify, X as OAUTH_PRESETS; or Custom with the authorize URL, token URL, API hosts and scopes), shows the redirect URI to register at the provider's console (https://<gateway>/connect/<id>/callback, with a copy button) and takes the client id and secret, stored sealed in D1 and never shown again; a Worker secret of the same name set from the terminal wins. Per row: Set client or Replace client, Forget pasted client, Connect for the organization (the organization's own account, for background work), Remove provider (registered rows only; refused while an app lists it). Connections below lists every connected account in the workspace (who, provider, scope sets, status, last used) with Disconnect. Each person's own accounts are under the account menu → Connected accounts (/settings/accounts): Connect |
Usage /admin/usage |
AI and provider calls per app, member and target for a month (usage_monthly): calls, failures, tokens, cost where the provider reports one. A Default monthly cap row above By app sets the workspace defaults; By app has a Monthly cap column (Unlimited by default; the call cap and, where set, the dollar cap, each with its progress; Paused by calls or Paused by dollars in red with Raise) and a Set cap dialog: calls per month, or dollars per month (counted only where the provider reports a price: OpenRouter, DataForSEO), or both. At either cap a brokered call gets 429 app_monthly_cap_exceeded until the next UTC month and a provider tool answers a tool error naming it. email and members are neither counted nor capped. |
Activity /admin/activity |
Every tool call an AI client made through the connector, allowed or blocked (mcp_tool_calls): when, who, app, tool with its risk, decision and reason, outcome, duration, result size; via names the wrapper (everyapp_call_read, everyapp_call_write); client_info is what the client declared at initialize. Filters by app, decision, risk and range; kept MCP_AUDIT_RETENTION_DAYS (90). Read-only. The Audit toggle (?view=audit) shows the audit log instead: every event the Gateway recorded (events, kept AUDIT_RETENTION_DAYS, 90): when, who, what (the type in plain words and its summary), subject; filters by who, type and range (events). |
Events /admin/events |
Signed webhooks and emails for what happens in the workspace (event_subscriptions, events, event_deliveries; docs/design/2026-10-events-out.md): Add subscription takes a webhook URL or an email to the owners (or owners and admins), and the events by type, by group (member.*) or Everything; a signing secret the Gateway generated is shown once. Per row: Send test, Deliveries, Edit, Disable or Enable, Remove (the built-in Cap alerts row, made with the first cap, is turned off instead). Deliveries lists 30 days with a Dead filter, Redeliver and the payload. The same from a terminal is pnpm everyapp events (the CLI by job). |
AI connections (OAuth consents) are each person's own, listed and revoked under AI connections in the account menu (/settings/connections); removing or deactivating a person ends all of theirs (Connections and revocation).
The same from a terminal: pnpm everyapp workspace <command> (packages/cli/src/commands/workspace/; every command takes --json, and all but rename and role take --org <slug> for another organization of the Gateway) acts under the operator's Cloudflare login on the Gateway's database, so it checks no role and mails nothing: invite and reset-link print the link to hand over. The same from an AI client: the workspace tools (packages/toolbus/src/workspace.ts, run by apps/every-app-gateway/src/server/toolbus/workspace-tools.ts) act as the caller, listed in the full listing only, to a role that reaches each tool's minRole (admin means owner or admin), never to a credential bound to some apps; they hand out no credential (no invite link, no reset link, no token value; an invite is mailed when the Gateway can), and every call is an Activity row (Workspace tools).
- Users:
pnpm everyapp workspace users;pnpm everyapp workspace invite <email> [--role admin],pnpm everyapp workspace invite-link <email|id>,pnpm everyapp workspace uninvite <email|id>;pnpm everyapp workspace role <email> owner|admin|member;pnpm everyapp workspace deactivate <email>,pnpm everyapp workspace reactivate <email>,pnpm everyapp workspace remove <email> --yes;pnpm everyapp workspace reset-link <email>. Tools:everyapp_workspace_users,everyapp_workspace_invite,everyapp_workspace_uninvite,everyapp_workspace_role(an admin changes members only),everyapp_workspace_deactivate,everyapp_workspace_reactivate,everyapp_workspace_remove(owner),everyapp_workspace_reset_email(mails the reset link to the member;EMAIL_NOT_CONFIGUREDwithout a sender). - Apps:
pnpm everyapp workspace apps;pnpm everyapp workspace app set <app> [--everyone on|off] [--name <name>] [--description <text>];pnpm everyapp workspace app access <app> [--add|--remove|--set <email>]…;pnpm everyapp workspace app cap <app> <n|off>orpnpm everyapp workspace app cap <app> --unlimited(no cap even under the workspace default);pnpm everyapp workspace cap default <n|off>(the workspace default for every app without its own). Tools:everyapp_workspace_apps,everyapp_workspace_app_set,everyapp_workspace_app_access,everyapp_workspace_app_access_set,everyapp_workspace_app_cap,everyapp_workspace_cap_default,everyapp_workspace_app_delete(owner; the catalog row, the Worker stays untilpnpm everyapp delete). - Groups:
pnpm everyapp workspace groups;pnpm everyapp workspace group create <name> [--description <text>],pnpm everyapp workspace group set <group> [--name <name>] [--description <text>],pnpm everyapp workspace group delete <group> --yes;pnpm everyapp workspace group members <group> [--add|--remove|--set <email>]…;pnpm everyapp workspace group apps <group> [--add|--remove|--set <app>]…. Tools:everyapp_workspace_groups,everyapp_workspace_group_create,everyapp_workspace_group_set,everyapp_workspace_group_delete,everyapp_workspace_group_members,everyapp_workspace_group_members_set,everyapp_workspace_group_apps,everyapp_workspace_group_apps_set. - Tokens and AI connections:
pnpm everyapp workspace tokens [--user <email>] [--all](every member's, never a value;--alladds revoked and expired ones) andpnpm everyapp workspace token revoke <id>;pnpm everyapp workspace connections [--user <email>]andpnpm everyapp workspace connection revoke <id>. Tools, for every member and only over their own:everyapp_my_tokens,everyapp_revoke_token,everyapp_my_connections,everyapp_revoke_connection. Nothing makes a token: Tokens → New token alone, since the value is shown once to its person. - Sign-in:
pnpm everyapp signin listandpnpm everyapp signin show <id>read what the tab shows;pnpm everyapp signin add <id>andpnpm everyapp signin remove <id>set and delete the provider's Worker secrets under the Cloudflare login. Tools, for owners and admins:everyapp_signin_listandeveryapp_signin_show({ id }), reads only: no tool adds or removes a sign-in provider. - Providers:
pnpm everyapp provider list,show <id>,presets,add --oauth <preset | spec>(prints the redirect URI;--client-idwith the secret on stdin sets the two Worker secrets at once),remove <id>,connections [--all | --user <email>]anddisconnect <id> [--user <email> | --organization](providers). Tools:everyapp_provider_listand a member's owneveryapp_provider_connectionsandeveryapp_provider_disconnect;everyapp_provider_add({ spec }or{ preset }),everyapp_provider_remove, and the two connection tools over any account, for owners and admins on a self-hosted Gateway. Pasting a client has no tool and no command: the dialog seals it, orpnpm everyapp secret set <ID>_CLIENT_ID <ID>_CLIENT_SECRETsets it as Worker secrets. Connecting is a browser flow (/connect/<id>), so it has neither. - Usage:
pnpm everyapp workspace usage [--month YYYY-MM];everyapp_workspace_usage. - Activity:
pnpm everyapp workspace activity [--app <app>] [--user <email>] [--decision allowed|blocked] [--risk read|write|destructive] [--since <time>] [--limit <n>] [--before <cursor>];everyapp_workspace_activity(one page, newest first;nextBeforefor the next). - Activity → Audit:
pnpm everyapp workspace audit [--actor <who>] [--type <type>] [--since <time>] [--limit <n>] [--before <cursor>];everyapp_workspace_audit(one page, newest first;nextBeforefor the next). - MCP apps from an owner's or admin's AI client:
everyapp_mcp_list,everyapp_mcp_show,everyapp_mcp_add(a credential by its setting's name, never its value),everyapp_mcp_on,everyapp_mcp_off,everyapp_mcp_refresh,everyapp_mcp_toolandeveryapp_mcp_remove(confirm: true); the terminal's arepnpm everyapp mcp …(the CLI by job). - Events (outbound webhooks and alert mail; the CLI's are
pnpm everyapp events …, the CLI by job):everyapp_workspace_events(the subscriptions, never a signing secret),everyapp_workspace_events_add(a webhook URL or email to owners or admins; a generated signing secret comes back once, in that answer, and opens nothing on the Gateway),everyapp_workspace_events_set,everyapp_workspace_events_remove(confirm: true; Cap alerts is turned off instead),everyapp_workspace_events_test(a ping and its first attempt),everyapp_workspace_event_deliveriesandeveryapp_workspace_event_redeliver. - The workspace itself:
pnpm everyapp workspace show(the owners, whether it can send mail, the counts) andpnpm everyapp workspace rename "<name>"(1 to 64 characters;WORKSPACE_NOT_CLAIMEDbefore the Gateway has an owner; the same as Manage workspace → Rename);everyapp_workspace_show,everyapp_workspace_rename.
The last owner's role is never changed anywhere (LAST_OWNER). Beside the workspace commands the CLI sets what the Gateway holds for people (secret set EMAIL_FROM EMAIL_FROM_NAME so invites and resets go out by mail from the Admin UI and the tools; access on so the Access policy admits the people invited). pnpm everyapp status --json reports the owner (data.owner, data.claimed), not the member list: that is workspace show and workspace users.
Cloudflare Access
When: a company's Gateway, before people are invited; it is free for up to 50 people and adds a second sign-in at Cloudflare's edge (a one-time PIN by email, or the company's identity provider). Recommend it to every person whose Gateway more than one person will use (the index).
The one command is pnpm everyapp access on (access; the setup file packages/cli/skills/everyapp/setup/access.md): the Zero Trust team (--team <name> when the account has none; the name is permanent), the one-time PIN, an allow policy with every member's and invitee's email (--email, --email-domain add more), two Access applications in front of the Gateway's host and the apps' hosts, and the three CLOUDFLARE_ACCESS_* Gateway settings. Rerunnable; run it again after inviting someone, since Access keeps its own list. pnpm everyapp access show reports; pnpm everyapp access off takes it down (--yes only when the person said so).
What changes for MCP clients: nothing, without Managed OAuth. The plan (packages/cli/src/lib/access/plan.ts) lets /mcp, /mcp/*, /oauth/token, /oauth/register and /.well-known/* past Access on the Gateway's host, /mcp on an app host whose manifest opts in (mcp: { by, why }), and each app's public routes on its own host; the person passes Access's login once in the browser at /oauth/authorize. With Access's Managed OAuth on the Gateway's application (switched on by hand, never by access on), Access itself is the OAuth server: MCP and API clients behind Access.
The CLI by job
Every route the CLI answers (commandPaths() in packages/cli/src/app.ts), run as pnpm everyapp … with --json when an agent drives it (json); every flag is on cli. A group (db, access, secret, mcp, email, events, workspace) answers --help with its subcommands; provider is mcp's old name, kept through launch week.
| Job | Command |
|---|---|
| Log in to Cloudflare | pnpm everyapp login (setup and deploy log in on their own when they must) |
| Install, upgrade or repair the Gateway | pnpm everyapp setup --domain <host> (first time: build, certificate, then the owner link the person opens; setup); pnpm everyapp update to move a running Gateway to the checkout's version |
| Know the state of everything | pnpm everyapp status --json: the Gateway's version and owner, every app (status, bound, setup, public routes, email), certificates, Access, deploys in progress, data.fixes (status) |
| Make a new app | pnpm everyapp create ../my-app from the every-app folder: a repository of its own beside the checkout, linked to it, one repository per app. For many apps, pnpm everyapp create my-app inside the checkout makes apps/my-app, untracked by git. Then Build an app |
| Run an app on this computer | pnpm everyapp dev in the app's directory (long-running, no --json; dev) |
| Put an app online, or update it | pnpm everyapp deploy in the app's directory, or pnpm run deploy there (deploy) |
| Set up an app that says Needs setup | pnpm everyapp configure <app> after its first deploy: each setting its manifest declares, required ones first, at a hidden prompt with where to get it; an agent pipes NAME=value lines in or adds --from-env; a value on the command line is refused. Before the first deploy, pnpm everyapp configure in the app's directory sets the Gateway's part (a provider's key, a capability's client). Live at once (secrets) |
| Set one key, and see what is set | pnpm everyapp secret set NAME [--app <id>] (a Gateway setting from anywhere, an app's own secret after its first deploy; the value never on the command line), pnpm everyapp secret unset NAME, pnpm everyapp secret list [<app>] (names and what each app still needs, never values) |
| Install someone's app; publish the person's own | pnpm everyapp install <GitHub URL>: the repository's latest release's everyapp-release.tar.gz; run again to update; NO_RELEASE when it publishes none; R2_NOT_ENABLED until the person enables R2 once in the Cloudflare dashboard (OpenCRM, OpenSEO and Agentic Inbox need it before their first install; OpenAnalytics doesn't). To publish: pnpm pack-for-app <app dir> --workflow from the checkout vendors the CLI and the SDK into the app's repository and adds a Release workflow that publishes the tarball on every push (in the checkout docs/runbooks/app-releases.md); pnpm everyapp release packs one by hand. The vendored CLI runs dev, db migrate and release, never deploy: deploys run from a checkout |
| Take an app off the Gateway | pnpm everyapp delete <id> (--purge deletes its data: only when the person asked) |
| Look inside an app's database | pnpm everyapp db query "<sql>" (a production write stops for confirmation), pnpm everyapp db migrate locally, pnpm everyapp db restore to undo the last deploy's migrations |
| Offer an MCP app to AI clients | pnpm everyapp mcp on dataforseo (built in); pnpm everyapp mcp add <url> (any remote MCP server; --name <id>, --auth and --secret <NAME> for how the Gateway signs in to it); pnpm everyapp mcp off <id> (its tools leave /mcp, everyone's access kept for on); pnpm everyapp mcp remove <id> (the row, everyone's access, the tokens bound to it and its tools snapshot go); pnpm everyapp mcp list (alias mcp ls: built in and added, on or off, key set or not); pnpm everyapp mcp show <id> (address, credential, status, last tool listing, every tool with its risk); pnpm everyapp mcp refresh <id> (drop the tools snapshot so the Gateway lists them again); pnpm everyapp mcp tool <id> <tool> --risk read (or write, destructive, annotations; --off leaves the tool out). provider on and provider off still run mcp on|off through launch week (hidden routes that say so first); provider add, provider list (alias provider ls), provider show and provider remove (alias provider rm) are the API provider registry's, the next row |
| Pick the model apps get when they ask for one | pnpm everyapp ai show (what the default resolves to now and why); pnpm everyapp ai list (alias ai ls: every provider the default could be, each key set or not); pnpm everyapp ai default <provider>[/<model>] (choose it; off for the shipped order: OpenRouter, Workers AI, OpenAI, Anthropic, Groq, Mistral, Gemini, the first whose key is set); pnpm everyapp ai gateway on [--id <name>] (Cloudflare AI Gateway in front of every model call; pnpm everyapp ai gateway off). Tools: everyapp_ai_show, everyapp_ai_default (AI) |
| Register an API provider for apps to call | pnpm everyapp provider list (the built-in catalog and this Gateway's rows, each key set or not, the apps listing each; alias provider ls); pnpm everyapp provider show <id> (the spec: hosts, how the key is sent, settings, who registered it); pnpm everyapp provider add <spec.json> (a spec the catalog lacks, from a file or an https URL; --replace rewrites a row and unbinds its key); pnpm everyapp provider remove <id> (alias provider rm; --force while an app lists it); then pnpm everyapp secret set <NAME> for its key, which binds the row to its hosts (providers). An OAuth provider people connect their accounts to: pnpm everyapp provider presets (GitHub, Notion, Linear, … and the built-in clients), pnpm everyapp provider add --oauth <preset> (the row and the redirect URI to register at the provider's console; --client-id with the secret piped as NAME=value, or --from-env, sets the client in the same run), pnpm everyapp provider connections (who connected what; --all, --user, --provider) and pnpm everyapp provider disconnect <id> (--user <email>, --organization or --all) (OAuth providers) |
| Send the organization's events out | pnpm everyapp events add <url> (a signed POST to an https URL; --email owners|admins instead for mail; --events <types>, --name, --secret or --secret-from-env), pnpm everyapp events list (alias events ls: where each subscription goes, what it takes, its last delivery), pnpm everyapp events remove <id> (Cap alerts is disabled instead), pnpm everyapp events enable <id> and pnpm everyapp events disable <id> (a paused one queues nothing), pnpm everyapp events test <id> (a ping, its delivery awaited), pnpm everyapp events deliveries [<id>] [--dead] (the last 30 days: event, subscription, attempts, status, last error), pnpm everyapp events redeliver <delivery>, pnpm everyapp events types (every type --events takes); an app emits its own with emit() (events) |
| An app's email addresses | pnpm everyapp email show, pnpm everyapp email set --sender "*@<domain>" --inbound <address>, pnpm everyapp email unset senders|inbound, in the app's directory (email); the Gateway's sender is secret set EMAIL_FROM EMAIL_FROM_NAME |
| Put Cloudflare Access in front | pnpm everyapp access on, pnpm everyapp access off, pnpm everyapp access show |
| Let people sign in with Google and the like | pnpm everyapp signin list (alias signin ls: each of google, microsoft, github, apple, cloudflare and oidc on, needs setup or off); pnpm everyapp signin show <id> (where to make the OAuth app, the redirect URL https://<gateway>/api/auth/callback/<id>, every setting and whether it is set); pnpm everyapp signin add <id> (asks at a terminal; unattended --client-id, --client-secret-from-env <VAR>, --issuer and --label for oidc, --tenant for microsoft; one Gateway version; the setup file packages/cli/skills/everyapp/setup/signin-<id>.md); pnpm everyapp signin remove <id> (--yes only when the person said so; accounts stay) |
| Manage the workspace | People, groups, who can open an app, caps, usage, what agents did: pnpm everyapp workspace --help lists the group: pnpm everyapp workspace show, rename, users, role, invite, invite-link, uninvite, deactivate, reactivate, remove, reset-link, groups, group create, group set, group delete, group members, group apps, apps, app set, app access, app cap, usage, activity, tokens, token revoke, connections, connection revoke, each beside its Admin tab under People and all on Managing the workspace; the same on /mcp as the everyapp_workspace_* tools for an owner or admin |
Not a command: making a personal access token (Tokens → New token: the value is shown once to its person); connecting an AI client (the client's own mcp add, Connecting clients). Not for a person's Gateway: pnpm everyapp teardown --account-id <id> --dry-run empties a dedicated test account named in EVERYAPP_TEST_ACCOUNTS and refuses any other (in the checkout docs/runbooks/onboarding-loop-test-accounts.md).
What to suggest next
The playbook is the proactive next-steps design; everyapp status has no Next: block on main yet (when it lands, rows 1 to 5, 8 and 9 print there and in data.next). Until then an agent reads the signals itself. Commands are pnpm everyapp ….
| # | Signal | Suggest | Command or URL |
|---|---|---|---|
| 1 | No AI key (OPENAI_API_KEY, OPENROUTER_API_KEY, WORKERS_AI_API_TOKEN) while an app lists providers, and no fix names it |
Apps that use AI need a key | secret set OPENROUTER_API_KEY (or the provider the apps name) |
| 2 | DATAFORSEO_API_KEY set, the dataforseo row absent or off |
The key is there; offer DataForSEO to AI clients | mcp on dataforseo |
| 2b | dataforseo on, its key unset |
DataForSEO is on but has no key | secret set DATAFORSEO_API_KEY |
| 3 | Access off, self-hosted, Worker uploaded | Put Cloudflare Access in front | access on |
| 4 | One member, an app live | Invite people | workspace invite <email> (prints the link to hand over), or https://<gateway>/admin/users |
| 5 | No live AI connection and no live token, and an app serves tools | Connect an AI client | https://<gateway>/mcp, /docs/connect-ai |
| 7 | An app needs setup | Already a fix (APP_NEEDS_SETUP); never repeated as a next |
configure <app> |
| 8 | No apps, an owner exists | Create the first app | create ../my-app, then Build an app |
| 9 | EMAIL_FROM and EMAIL_FROM_NAME not both set, and more than one member or an app lists email |
Invites and resets go out by link until email is set | secret set EMAIL_FROM EMAIL_FROM_NAME |
| 10 | The most-used apps (usage_monthly.calls this month; allowed mcp_tool_calls in 30 days) |
Nothing: a ranking for where to start, never a nudge | workspace usage --json; everyapp_workspace_usage; Usage |
Noise rules, which bind an agent as they bind the Gateway: rows 1 to 4 and 7 to 9 are for owners and admins, and a member hears one thing, connect an AI client (everyapp_whoami says which the person is; row 10 is an order members see, not a nudge); once per state, said while the signal is true and dropped when it isn't, never a list of what was suggested; at most four at a time, in the table's order, never one the person cannot act on, never a fix status already prints; never "you have not used X" to a person (usage ranks, it does not prompt) and no cap nudges (a cap is opt-in); one command or one URL per suggestion, and a value (a key) never through the chat (secrets).
Where each signal is read: pnpm everyapp status --json (data.apps[] with status, bound, publicRoutes, email and setup; data.owner, data.claimed, data.access, data.mode; data.fixes[] as { code, severity, message, run, note?, fix? } with the codes in ProblemCode, packages/cli/src/commands/status/problems.ts) for rows 3, 7 and 8, every line explained on status; pnpm everyapp secret list --json outside an app directory (data.gateway.names, the Gateway Worker's settings, names only; data.apps[].setup) for rows 1, 2, 2b and 9, with which apps list providers or email in each manifest or data.apps[].setup.unmet[].need; pnpm everyapp mcp list --json (data.providers[] with id, name, on and key: { name, set }; data.next already carrying mcp on <id> and secret set <KEY>) for rows 2 and 2b in one call; from an AI client, everyapp_list_apps (a tools count per usable app; available: false with reason for one that needs setup) and everyapp_whoami (user.role, connection.kind, access, apps), where row 5's "serves tools" is a count above zero; pnpm everyapp workspace users --json, pnpm everyapp workspace connections --json, pnpm everyapp workspace tokens --json and pnpm everyapp workspace usage --json for rows 4, 5 and 10 (what Users, AI connections, Tokens and Usage show); from an AI client, everyapp_workspace_users and everyapp_workspace_usage as an owner or admin, and a member's own everyapp_my_connections and everyapp_my_tokens.
Other MCP servers to recommend
A server the whole team should reach goes on the Gateway as an MCP app (pnpm everyapp mcp add <url>; the Gateway holds its credential), never into each person's client. For the client itself two are worth adding, and nothing else. The Gateway's own connector first: https://<gateway>/mcp, every app the caller can reach plus the everyapp_ built-ins, behind the Gateway's OAuth and consent (Connecting clients); every member should have it. Cloudflare's, below, is for the owner or operator, the person whose Cloudflare login ran everyapp setup. The rule for both, decided for the launch (TODO.md, "Agent-forward layer (2026-10-24)"): everyapp setup and everyapp create install none and print nothing about them; an agent names one in a single line when the person's task needs it and waits for a yes; it never writes a client config unasked, and never one the repository shares (.mcp.json from Claude Code's --scope project, .cursor/mcp.json, .codex/config.toml). The same rule, with the add and remove lines per client, is the setup skill's section "Optional: MCP servers worth having beside EveryApp" (packages/cli/skills/everyapp/setup/gateway.md); the person's page is /docs/connect-ai.
Cloudflare's MCP server
https://mcp.cloudflare.com/mcp (Streamable HTTP). Four tools: search and execute (code mode over the Cloudflare API: the agent writes JavaScript that is run on Cloudflare's side, the token outside the sandbox), docs (developers.cloudflare.com) and whoami. Auth: OAuth with the person's Cloudflare login (Minimal on the consent page is the least; a call that lacks a scope asks the person to add it), or an API token as a bearer header for automation. Scope: the whole account, as the person, within the granted permissions; execute takes an account_id. There is no Gateway narrowing.
When it helps: reading what everyapp status and everyapp access show do not report about the account the Gateway runs in (the zone's records, the Workers and their versions, the D1 database, the Access team and policies, email, logs, API tokens, the plan and the bill). When it is noise: anything everyapp does. The CLI writes the Gateway's database and the deploy ledger beside Cloudflare, and a deploy refuses to replace a Worker last changed in the dashboard or through the API until a person confirms in a terminal (assertReplaceable in packages/cli/src/lib/cf/deploy.ts; rerun_interactive), so a Worker, secret, record or policy written through this server stops the next deploy. Read before write; a write is a live API call on the whole account, as the person, with no undo. When the person says yes, in Claude Code: claude mcp add --transport http cloudflare https://mcp.cloudflare.com/mcp, then they authenticate under /mcp; Codex, claude.ai, Claude Desktop and Cursor are in the setup skill's section.
GitHub
Nothing to add. pnpm everyapp install <GitHub URL> fetches releases/latest/download/everyapp-release.tar.gz anonymously (deploy). For what surrounds a repository (which release, its README, an issue, the Actions runs of an app the person builds), a terminal harness has gh, and claude.ai has its built-in GitHub connector.
Not recommended
Cloudflare's separate docs server https://docs.mcp.cloudflare.com/mcp (the API server's docs tool is the same search) and its product servers. A docs MCP for EveryApp: none; the agent docs are Markdown at https://everyapp.com/docs/agent/<page>.md and /llms.txt, fetched without MCP.
Sources
packages/cli/src/app.ts(commandPaths),packages/cli/src/commands/status/problems.ts,packages/cli/src/commands/configure/command.ts,packages/cli/src/commands/provider/index.ts(themcpgroup),packages/perimeter/src/registry/remoteMcpApps.ts,packages/cli/src/commands/workspace/command.tsandindex.ts,packages/cli/src/lib/access/plan.ts,packages/cli/src/lib/app/settings.ts,scripts/pack-for-app.mjspackages/toolbus/src/builtins.ts,workspace.ts,view.tsandremote/;apps/every-app-gateway/src/server/toolbus/gateway-mcp.tsandworkspace-tools.ts;apps/every-app-gateway/src/server/provider-apps/;packages/sdk/src/internal/providerApps.tsapps/every-app-gateway/src/routes/_app/admin.tsx;apps/every-app-gateway/src/server/org-roles.ts,app-cap.ts,services/AdminService.ts(a delete that deactivates instead),services/InvitationService.ts,services/UserPatService.ts;apps/every-app-gateway/src/db/usage.schema.ts,mcp.schema.tsdocs/design/2026-10-teams.md,docs/design/2026-10-mcp-provider-apps.md,docs/design/2026-10-mcp-apps-ui.md,docs/design/2026-10-mcp-by-url.md, the proactive next-steps design (PR #588, not on main),docs/runbooks/cloudflare-access.md,docs/runbooks/app-releases.md,docs/security-model.md; the MCP-servers rule: PR #585 (TODO.md, the setup skill, connect-ai)- https://developers.cloudflare.com/agents/model-context-protocol/cloudflare/servers-for-cloudflare/, https://github.com/cloudflare/mcp, https://developers.cloudflare.com/changelog/post/2026-10-19-cloudflare-mcp-step-up/, https://code.claude.com/docs/en/mcp and
claude mcp add --helpof 2.1.309 (read 2026-10-24)
AI: the default model provider and AI Gateway
How an app gets a chat model without naming a provider: the manifest's ai.chat, the SDK's ai(), the /api/ai/default route, the order the Gateway resolves the default in (OpenRouter, Workers AI, OpenAI, Anthropic, Groq, Mistral, Gemini), everyapp ai default|show|list|gateway with their --json data and the MCP twins, Cloudflare AI Gateway in front of every provider, what each AI entry's fields mean, the usage by model, the ai.default_changed event, and why OpenRouter is the first default and AI Gateway is never one.
Cloudflare Access
How to put Cloudflare Access in front of a self-hosted Gateway (OIDC sign-in or the outer ring), every CLOUDFLARE_ACCESS_* setting, what everyapp access on, off and show change, which paths stay bypassed and why, how MCP clients behave behind Access, and how to get back in.