everyapp 0.2.2 → 0.3.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +6 -77
  2. package/bin/everyapp.js +235 -0
  3. package/dist/access-F3GKBKAW.js +1 -0
  4. package/dist/activity-4MFMH5JP.js +12 -0
  5. package/dist/apps-63K2DGVT.js +9 -0
  6. package/dist/chunk-2UFJRKEE.js +4 -0
  7. package/dist/chunk-3AAHHUJC.js +11 -0
  8. package/dist/chunk-3Z53CH4F.js +6 -0
  9. package/dist/chunk-5ZTFC6DK.js +1 -0
  10. package/dist/chunk-6O3GJS5H.js +15 -0
  11. package/dist/chunk-74EST4VW.js +2 -0
  12. package/dist/chunk-7LG3F4FF.js +10 -0
  13. package/dist/chunk-AUDGOIHE.js +1 -0
  14. package/dist/chunk-BHMRY53V.js +2 -0
  15. package/dist/chunk-DQWOXSL3.js +32 -0
  16. package/dist/chunk-E3EPK27P.js +10 -0
  17. package/dist/chunk-E7EUXUVD.js +1 -0
  18. package/dist/chunk-ECLJ5IAL.js +126 -0
  19. package/dist/chunk-EQX4GKJ2.js +4 -0
  20. package/dist/chunk-EUNGJMJ6.js +20 -0
  21. package/dist/chunk-F6IH47GT.js +4 -0
  22. package/dist/chunk-G64S77GC.js +33 -0
  23. package/dist/chunk-GD2JZMD3.js +1 -0
  24. package/dist/chunk-GRFPP4UW.js +7 -0
  25. package/dist/chunk-IA534DGW.js +10 -0
  26. package/dist/chunk-IG26HYRR.js +45 -0
  27. package/dist/chunk-IZEOAOKL.js +6 -0
  28. package/dist/chunk-JYKRUS5C.js +1 -0
  29. package/dist/chunk-KMAOZRV4.js +18 -0
  30. package/dist/chunk-MC56CUQI.js +7 -0
  31. package/dist/chunk-MDORVBPD.js +1 -0
  32. package/dist/chunk-N4E5YE4X.js +5 -0
  33. package/dist/chunk-NJFWEYX7.js +1 -0
  34. package/dist/chunk-OEOVNJAN.js +1 -0
  35. package/dist/chunk-OVKVV6MK.js +2 -0
  36. package/dist/chunk-PL6EORDJ.js +15 -0
  37. package/dist/chunk-PMPIMHKG.js +6 -0
  38. package/dist/chunk-QZWSSWMP.js +22 -0
  39. package/dist/chunk-R4CGF622.js +2 -0
  40. package/dist/chunk-RFVMR32Y.js +1 -0
  41. package/dist/chunk-RQFHVU3Y.js +25 -0
  42. package/dist/chunk-SAT3PGZU.js +57 -0
  43. package/dist/chunk-SPPR6WCI.js +1 -0
  44. package/dist/chunk-TPWSGRNT.js +30 -0
  45. package/dist/chunk-VVQRET35.js +2 -0
  46. package/dist/chunk-VXJQGJ7Y.js +2 -0
  47. package/dist/chunk-WEM3WLOC.js +1 -0
  48. package/dist/chunk-Y3VIFPN5.js +1 -0
  49. package/dist/chunk-YJBYZWSP.js +22 -0
  50. package/dist/chunk-ZYL2ZHCF.js +98 -0
  51. package/dist/configure-2KMHM22T.js +8 -0
  52. package/dist/create-ELEJMZBS.js +22 -0
  53. package/dist/db-MZIAKGBN.js +9 -0
  54. package/dist/delete-H47KPJSB.js +3 -0
  55. package/dist/deploy-HGFJLLUO.js +1 -0
  56. package/dist/dev-62VA7UEM.js +86 -0
  57. package/dist/email-NNFD3VVB.js +10 -0
  58. package/dist/events-JDY76EG6.js +15 -0
  59. package/dist/groups-NQFXDZZP.js +8 -0
  60. package/dist/index.js +92 -1
  61. package/dist/install-JTZWRZIL.js +1 -0
  62. package/dist/login-P6LYQQWP.js +1 -0
  63. package/dist/mcp-NCFWEBMD.js +1 -0
  64. package/dist/provider-WVBI2VED.js +13 -0
  65. package/dist/release-6FYSPXXA.js +1 -0
  66. package/dist/restore-XBU7DOJV.js +3 -0
  67. package/dist/secret-ML5EXS3O.js +1 -0
  68. package/dist/setup-IEXCISLP.js +1 -0
  69. package/dist/status-OPLPKJ4U.js +4 -0
  70. package/dist/teardown-3JMMLK6O.js +22 -0
  71. package/dist/update-37ZDATLR.js +1 -0
  72. package/dist/workspace-DAFZVYQ2.js +21 -0
  73. package/package.json +30 -27
  74. package/skills/build-every-app/SKILL.md +199 -0
  75. package/skills/build-every-app/patterns.md +134 -0
  76. package/skills/everyapp/SKILL.md +292 -0
  77. package/skills/everyapp/mcp.md +336 -0
  78. package/skills/everyapp/security-review.md +61 -0
  79. package/skills/everyapp/setup/README.md +263 -0
  80. package/skills/everyapp/setup/access.md +178 -0
  81. package/skills/everyapp/setup/context.md +117 -0
  82. package/skills/everyapp/setup/dataforseo.md +287 -0
  83. package/skills/everyapp/setup/email.md +366 -0
  84. package/skills/everyapp/setup/gateway.md +243 -0
  85. package/skills/everyapp/setup/google.md +360 -0
  86. package/skills/everyapp/setup/microsoft-365.md +281 -0
  87. package/skills/everyapp/setup/openai.md +318 -0
  88. package/skills/everyapp/setup/openrouter.md +309 -0
  89. package/skills/everyapp/setup/providers.md +353 -0
  90. package/skills/everyapp/setup/remote-mcp.md +199 -0
  91. package/skills/everyapp/setup/slack.md +344 -0
  92. package/skills/everyapp/setup/workers-ai.md +138 -0
  93. package/bin/__everyapp_bash_complete.js +0 -12
  94. package/dist/bash-complete.js +0 -3
  95. package/dist/chunk-7BOQJFI5.js +0 -8
  96. package/dist/chunk-7YVJFS4A.js +0 -1
  97. package/dist/chunk-BIXKPCDH.js +0 -2
  98. package/dist/chunk-DLGPLHBH.js +0 -47
  99. package/dist/chunk-FD6K2YA7.js +0 -9
  100. package/dist/chunk-GAJEQYJH.js +0 -39
  101. package/dist/chunk-O2KDOP5R.js +0 -13
  102. package/dist/chunk-OI2MBGBG.js +0 -4
  103. package/dist/chunk-POSDLD3G.js +0 -8
  104. package/dist/chunk-RB5D2R45.js +0 -1
  105. package/dist/chunk-U4LIQ5VR.js +0 -1
  106. package/dist/chunk-VEYSNPDH.js +0 -3
  107. package/dist/chunk-VP6SKW44.js +0 -7
  108. package/dist/chunk-WO3NE7ZU.js +0 -7
  109. package/dist/chunk-XTO2VTPY.js +0 -6
  110. package/dist/chunk-YJ2DKIZS.js +0 -1
  111. package/dist/create-DYQ3NBWJ.js +0 -22
  112. package/dist/deploy-PYTCMDGV.js +0 -7
  113. package/dist/deploy-RMAHOA4Z.js +0 -55
  114. package/dist/dev-SAE237FS.js +0 -0
  115. package/dist/generateConfig-46Z3ERF3.js +0 -1
  116. package/dist/login-B6EF3SMX.js +0 -1
  117. package/dist/logout-XMKZBLNV.js +0 -1
  118. package/dist/remoteD1Shell-A67JMO3H.js +0 -6
  119. package/dist/setupLocal-TZJUW5ES.js +0 -6
  120. package/gateway/every-app-gateway-build.tar.gz +0 -0
@@ -0,0 +1,353 @@
1
+ <!-- generated: pnpm -C packages/cli docs:update writes this file from the built-in catalog (packages/sdk/src/internal/capabilities.ts, through packages/cli/src/docs/providersCatalog.ts). Edit the catalog, never this file: a test fails CI when it is stale. -->
2
+
3
+ # Every catalog provider: its settings, its key and one check
4
+
5
+ For a coding agent setting up a provider the Gateway's built-in catalog has. Each provider is a section under its id, so `setup/providers.md#<id>` points at it. Where the provider has a file of its own in this folder (its **Guide**), follow that file and read this section as its summary. Read [README.md](README.md) first: its rules hold here too, above all that a key never goes through the chat.
6
+
7
+ A provider registered on one Gateway (`pnpm everyapp provider add`) is not in this file: `pnpm everyapp provider show <id>` prints its whole spec (its hint, settings, hosts, where the key comes from and its smoke request). The catalog has 23 providers: 2 API-key, 3 AI, 18 OAuth clients.
8
+
9
+ The smoke request needs the key, so it runs where the key is: the person's terminal, with the variable they read in hidden, or through the app that uses it. It is one call that costs nothing (unless marked charged).
10
+
11
+ ## How a value gets in
12
+
13
+ The three ways of [README.md](README.md), one line each (the rules, and the codes a failure carries, are there):
14
+
15
+ - **The person types it**, in their own terminal in the `every-app` folder: `pnpm everyapp configure <app id>` (everything the app needs) or `pnpm everyapp secret set NAME` (one name), each value at a hidden prompt.
16
+ - **A command produced it**: pipe it straight in, `… | pnpm everyapp secret set NAME --json`, so it is never shown.
17
+ - **It is in an environment variable** the person read in hidden: `pnpm everyapp secret set NAME --from-env NAME --json`, or `pnpm everyapp configure <app id> --from-env --json`.
18
+
19
+ ## Providers
20
+
21
+ | Id | Name | Kind | Settings | Guide |
22
+ | --- | --- | --- | --- | --- |
23
+ | [`dataforseo`](#dataforseo) | DataForSEO | API key | `DATAFORSEO_API_KEY` | [dataforseo.md](dataforseo.md) |
24
+ | [`context`](#context) | Context.dev | API key | `CONTEXT_API_KEY` | [context.md](context.md) |
25
+ | [`openai`](#openai) | OpenAI | AI | `OPENAI_API_KEY` | [openai.md](openai.md) |
26
+ | [`openrouter`](#openrouter) | OpenRouter | AI | `OPENROUTER_API_KEY` | [openrouter.md](openrouter.md) |
27
+ | [`workers-ai`](#workers-ai) | Workers AI | AI | `WORKERS_AI_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` (set by `everyapp setup`) | [workers-ai.md](workers-ai.md) |
28
+ | [`linkedin`](#linkedin) | LinkedIn | OAuth client | `LINKEDIN_CLIENT_ID`, `LINKEDIN_CLIENT_SECRET` | |
29
+ | [`facebook`](#facebook) | Facebook | OAuth client | `FACEBOOK_APP_ID`, `FACEBOOK_APP_SECRET` | |
30
+ | [`instagram`](#instagram) | Instagram | OAuth client | `INSTAGRAM_APP_ID`, `INSTAGRAM_APP_SECRET` | |
31
+ | [`threads`](#threads) | Threads | OAuth client | `THREADS_APP_ID`, `THREADS_APP_SECRET` | |
32
+ | [`youtube`](#youtube) | YouTube | OAuth client | `YOUTUBE_CLIENT_ID`, `YOUTUBE_CLIENT_SECRET` | [google.md](google.md) |
33
+ | [`tiktok`](#tiktok) | TikTok | OAuth client | `TIKTOK_CLIENT_ID`, `TIKTOK_CLIENT_SECRET` | |
34
+ | [`tiktok-business`](#tiktok-business) | TikTok Business | OAuth client | `TIKTOK_BUSINESS_CLIENT_ID`, `TIKTOK_BUSINESS_CLIENT_SECRET` | |
35
+ | [`reddit`](#reddit) | Reddit | OAuth client | `REDDIT_CLIENT_ID`, `REDDIT_CLIENT_SECRET` | |
36
+ | [`pinterest`](#pinterest) | Pinterest | OAuth client | `PINTEREST_CLIENT_ID`, `PINTEREST_CLIENT_SECRET` | |
37
+ | [`discord`](#discord) | Discord | OAuth client | `DISCORD_CLIENT_ID`, `DISCORD_CLIENT_SECRET` | |
38
+ | [`slack`](#slack) | Slack | OAuth client | `SLACK_CLIENT_ID`, `SLACK_CLIENT_SECRET` | [slack.md](slack.md) |
39
+ | [`mastodon`](#mastodon) | Mastodon | OAuth client | `MASTODON_CLIENT_ID`, `MASTODON_CLIENT_SECRET`, `MASTODON_URL` | |
40
+ | [`kick`](#kick) | Kick | OAuth client | `KICK_CLIENT_ID`, `KICK_CLIENT_SECRET` | |
41
+ | [`twitch`](#twitch) | Twitch | OAuth client | `TWITCH_CLIENT_ID`, `TWITCH_CLIENT_SECRET` | |
42
+ | [`tumblr`](#tumblr) | Tumblr | OAuth client | `TUMBLR_CLIENT_ID`, `TUMBLR_CLIENT_SECRET` | |
43
+ | [`dribbble`](#dribbble) | Dribbble | OAuth client | `DRIBBBLE_CLIENT_ID`, `DRIBBBLE_CLIENT_SECRET` | |
44
+ | [`google-workspace`](#google-workspace) | Google (Gmail, Calendar, Search Console and Analytics) | OAuth client | `GOOGLE_WORKSPACE_CLIENT_ID`, `GOOGLE_WORKSPACE_CLIENT_SECRET` | [google.md](google.md) |
45
+ | [`microsoft-365`](#microsoft-365) | Microsoft 365 (Outlook mail and calendar) | OAuth client | `MICROSOFT_365_CLIENT_ID`, `MICROSOFT_365_CLIENT_SECRET` | [microsoft-365.md](microsoft-365.md) |
46
+
47
+ Gateway services have no key of this kind: `email`, `members` (sending mail is [email.md](email.md); the members list needs nothing).
48
+
49
+ ## API-key providers
50
+
51
+ ### dataforseo
52
+
53
+ **DataForSEO** (`api_key`): SEO data: keyword metrics, live search results, domain rankings, backlinks.
54
+
55
+ - **Settings:** `DATAFORSEO_API_KEY`
56
+ - **What the key is:** The API login and password from API Access, as login:password (or that pair base64-encoded); the Gateway sends them as HTTP Basic. login:password, or its base64; never the dashboard sign-in password.
57
+ - **Where the key comes from:** https://app.dataforseo.com/api-access
58
+ - **API reference:** https://docs.dataforseo.com/v3/
59
+ - **How it is sent:** `Authorization: Basic <DATAFORSEO_API_KEY>`, the value `login:password` base64-encoded (or sent as it is when it holds no colon: already encoded), to `api.dataforseo.com`, `sandbox.dataforseo.com` only, over https
60
+ - **What apps may do:** access `read`; GET, POST on any grant; account-wide paths refused: `tasks_ready`, `tasks_fixed`, `id_list`, `errors`, `appendix/user_data`, `appendix/webhook_resend`
61
+ - **Smoke request:** `GET https://api.dataforseo.com/v3/appendix/user_data`, expecting 200; free. Account-wide, so the Gateway refuses it for apps; run it from the person's terminal.
62
+ - **Cost:** per call. A Google SERP $0.002 per 10 results; a Labs task $0.012 plus $0.00012 per item. The Gateway reads each answer's `cost` field (US dollars) into the usage counters.
63
+ - **Rate:** not recorded
64
+ - **Verified:** 2026-10-25, live
65
+ - **Set it:** `pnpm everyapp secret set DATAFORSEO_API_KEY`, or `pnpm everyapp configure <app id>` for everything an app needs
66
+ - **Guide:** [dataforseo.md](dataforseo.md)
67
+
68
+ ### context
69
+
70
+ **Context.dev** (`api_key`): Scrapes and renders web pages, JavaScript included.
71
+
72
+ - **Settings:** `CONTEXT_API_KEY`
73
+ - **What the key is:** An API key from the Context.dev dashboard; the Gateway puts it on every call as a bearer token.
74
+ - **Where the key comes from:** https://context.dev/
75
+ - **How it is sent:** `Authorization: Bearer <CONTEXT_API_KEY>`, to `api.context.dev` only, over https
76
+ - **What apps may do:** access `read`; GET, POST on any grant
77
+ - **Smoke request:** none recorded
78
+ - **Cost:** not recorded
79
+ - **Rate:** not recorded
80
+ - **Verified:** 2026-10-25, live
81
+ - **Set it:** `pnpm everyapp secret set CONTEXT_API_KEY`, or `pnpm everyapp configure <app id>` for everything an app needs
82
+ - **Guide:** [context.md](context.md)
83
+
84
+ ## AI providers
85
+
86
+ ### openai
87
+
88
+ **OpenAI** (`ai`): OpenAI's models: responses, chat, embeddings, audio, images.
89
+
90
+ - **Settings:** `OPENAI_API_KEY`
91
+ - **What the key is:** A secret key from the API keys page; the Gateway puts it on every call as a bearer token.
92
+ - **Where the key comes from:** https://platform.openai.com/api-keys
93
+ - **API reference:** https://platform.openai.com/docs/api-reference
94
+ - **How it is sent:** `Authorization: Bearer <OPENAI_API_KEY>`, to `api.openai.com` only, over https
95
+ - **What apps may do:** list it under `providers` and call `/api/ai/openai/…` with `createGatewayFetch()`: POST to `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/audio/speech`, `/v1/audio/transcriptions`, `/v1/audio/translations`, `/v1/images/generations`, `/v1/images/edits`, `/v1/images/variations`, and more only where both `AI_PROXY_EXTRA_ROUTES` and the app's `ai.routes` allow it
96
+ - **Smoke request:** none recorded
97
+ - **Cost:** not recorded
98
+ - **Rate:** not recorded
99
+ - **Verified:** 2026-10-25, live
100
+ - **Set it:** `pnpm everyapp secret set OPENAI_API_KEY`, or `pnpm everyapp configure <app id>` for everything an app needs
101
+ - **Guide:** [openai.md](openai.md)
102
+
103
+ ### openrouter
104
+
105
+ **OpenRouter** (`ai`): One key for many models, through OpenAI's API shape.
106
+
107
+ - **Settings:** `OPENROUTER_API_KEY`
108
+ - **What the key is:** An API key from OpenRouter's keys page; the Gateway puts it on every call as a bearer token.
109
+ - **Where the key comes from:** https://openrouter.ai/settings/keys
110
+ - **API reference:** https://openrouter.ai/docs
111
+ - **How it is sent:** `Authorization: Bearer <OPENROUTER_API_KEY>`, to `openrouter.ai` only, over https
112
+ - **What apps may do:** list it under `providers` and call `/api/ai/openrouter/…` with `createGatewayFetch()`: POST to `/api/v1/chat/completions`, `/api/v1/completions`, `/api/v1/responses`, `/api/v1/embeddings`
113
+ - **Smoke request:** none recorded
114
+ - **Cost:** not recorded
115
+ - **Rate:** not recorded
116
+ - **Verified:** 2026-10-25, live
117
+ - **Set it:** `pnpm everyapp secret set OPENROUTER_API_KEY`, or `pnpm everyapp configure <app id>` for everything an app needs
118
+ - **Guide:** [openrouter.md](openrouter.md)
119
+
120
+ ### workers-ai
121
+
122
+ **Workers AI** (`ai`): Cloudflare's models, in the Gateway's own account.
123
+
124
+ - **Settings:** `WORKERS_AI_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` (set by `everyapp setup`)
125
+ - **What the key is:** A Cloudflare API token with Workers AI Read (the Workers AI page's prefilled token); the account is the Gateway's own.
126
+ - **Where the key comes from:** https://dash.cloudflare.com/profile/api-tokens
127
+ - **API reference:** https://developers.cloudflare.com/workers-ai/
128
+ - **How it is sent:** `Authorization: Bearer <WORKERS_AI_API_TOKEN>`, to `api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai` only, over https
129
+ - **What apps may do:** list it under `providers` and call `/api/ai/workers-ai/…` with `createGatewayFetch()`: POST to `/v1/chat/completions`, `/v1/embeddings`, `/v1/responses`
130
+ - **Smoke request:** none recorded
131
+ - **Cost:** not recorded
132
+ - **Rate:** not recorded
133
+ - **Verified:** 2026-10-25, live
134
+ - **Set it:** `pnpm everyapp secret set WORKERS_AI_API_TOKEN`, or `pnpm everyapp configure <app id>` for everything an app needs
135
+ - **Guide:** [workers-ai.md](workers-ai.md)
136
+
137
+ ## OAuth clients
138
+
139
+ ### linkedin
140
+
141
+ **LinkedIn** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
142
+
143
+ - **Settings:** `LINKEDIN_CLIENT_ID`, `LINKEDIN_CLIENT_SECRET`
144
+ - **Where the client comes from:** https://www.linkedin.com/developers/apps
145
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/linkedin`, `https://<app>.<APP_BASE_DOMAIN>/integrations/social/linkedin-page`
146
+ - **How it is sent:** POST `www.linkedin.com/oauth/v2/accessToken` (the client in the form body)
147
+ - **Scope sets an app lists:** none: the whole client is the grant
148
+ - **Set it:** `pnpm everyapp secret set LINKEDIN_CLIENT_ID LINKEDIN_CLIENT_SECRET`
149
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
150
+
151
+ ### facebook
152
+
153
+ **Facebook** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
154
+
155
+ - **Settings:** `FACEBOOK_APP_ID`, `FACEBOOK_APP_SECRET`
156
+ - **Where the client comes from:** https://developers.facebook.com/apps
157
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/facebook`, `https://<app>.<APP_BASE_DOMAIN>/integrations/social/instagram`
158
+ - **How it is sent:** GET/POST `graph.facebook.com/v<version>/oauth/access_token` (the client in the query)
159
+ - **Scope sets an app lists:** none: the whole client is the grant
160
+ - **Set it:** `pnpm everyapp secret set FACEBOOK_APP_ID FACEBOOK_APP_SECRET`
161
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
162
+
163
+ ### instagram
164
+
165
+ **Instagram** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
166
+
167
+ - **Settings:** `INSTAGRAM_APP_ID`, `INSTAGRAM_APP_SECRET`
168
+ - **Where the client comes from:** https://developers.facebook.com/apps
169
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/instagram-standalone`
170
+ - **How it is sent:** POST `api.instagram.com/oauth/access_token` (the client in the form body); GET `graph.instagram.com/access_token` (the client in the query)
171
+ - **Scope sets an app lists:** none: the whole client is the grant
172
+ - **Set it:** `pnpm everyapp secret set INSTAGRAM_APP_ID INSTAGRAM_APP_SECRET`
173
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
174
+
175
+ ### threads
176
+
177
+ **Threads** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
178
+
179
+ - **Settings:** `THREADS_APP_ID`, `THREADS_APP_SECRET`
180
+ - **Where the client comes from:** https://developers.facebook.com/apps
181
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/threads`
182
+ - **How it is sent:** GET/POST `graph.threads.net/oauth/access_token` (the client in the query); GET `graph.threads.net/access_token` (the client in the query)
183
+ - **Scope sets an app lists:** none: the whole client is the grant
184
+ - **Set it:** `pnpm everyapp secret set THREADS_APP_ID THREADS_APP_SECRET`
185
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
186
+
187
+ ### youtube
188
+
189
+ **YouTube** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
190
+
191
+ - **Settings:** `YOUTUBE_CLIENT_ID`, `YOUTUBE_CLIENT_SECRET`
192
+ - **Where the client comes from:** https://console.cloud.google.com/apis/credentials
193
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/youtube`, `https://<app>.<APP_BASE_DOMAIN>/integrations/social/gmb`
194
+ - **How it is sent:** POST `oauth2.googleapis.com/token` (the client in the form body)
195
+ - **Scope sets an app lists:** none: the whole client is the grant
196
+ - **Set it:** `pnpm everyapp secret set YOUTUBE_CLIENT_ID YOUTUBE_CLIENT_SECRET`
197
+ - **Guide:** [google.md](google.md)
198
+
199
+ ### tiktok
200
+
201
+ **TikTok** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
202
+
203
+ - **Settings:** `TIKTOK_CLIENT_ID`, `TIKTOK_CLIENT_SECRET`
204
+ - **Where the client comes from:** https://developers.tiktok.com/apps
205
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/tiktok`
206
+ - **How it is sent:** POST `open.tiktokapis.com/v2/oauth/token/` (the client in the form body)
207
+ - **Scope sets an app lists:** none: the whole client is the grant
208
+ - **Set it:** `pnpm everyapp secret set TIKTOK_CLIENT_ID TIKTOK_CLIENT_SECRET`
209
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
210
+
211
+ ### tiktok-business
212
+
213
+ **TikTok Business** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
214
+
215
+ - **Settings:** `TIKTOK_BUSINESS_CLIENT_ID`, `TIKTOK_BUSINESS_CLIENT_SECRET`
216
+ - **Where the client comes from:** https://business-api.tiktok.com/portal/apps
217
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/tiktok-business/`
218
+ - **How it is sent:** POST `business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/token/` (the client in the JSON body); POST `business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/refresh_token/` (the client in the JSON body)
219
+ - **Scope sets an app lists:** none: the whole client is the grant
220
+ - **Set it:** `pnpm everyapp secret set TIKTOK_BUSINESS_CLIENT_ID TIKTOK_BUSINESS_CLIENT_SECRET`
221
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
222
+
223
+ ### reddit
224
+
225
+ **Reddit** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
226
+
227
+ - **Settings:** `REDDIT_CLIENT_ID`, `REDDIT_CLIENT_SECRET`
228
+ - **Where the client comes from:** https://www.reddit.com/prefs/apps
229
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/reddit`
230
+ - **How it is sent:** POST `www.reddit.com/api/v1/access_token` (the client in the Basic header)
231
+ - **Scope sets an app lists:** none: the whole client is the grant
232
+ - **Set it:** `pnpm everyapp secret set REDDIT_CLIENT_ID REDDIT_CLIENT_SECRET`
233
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
234
+
235
+ ### pinterest
236
+
237
+ **Pinterest** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
238
+
239
+ - **Settings:** `PINTEREST_CLIENT_ID`, `PINTEREST_CLIENT_SECRET`
240
+ - **Where the client comes from:** https://developers.pinterest.com/apps/
241
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/pinterest`
242
+ - **How it is sent:** POST `api.pinterest.com/v5/oauth/token` (the client in the Basic header)
243
+ - **Scope sets an app lists:** none: the whole client is the grant
244
+ - **Set it:** `pnpm everyapp secret set PINTEREST_CLIENT_ID PINTEREST_CLIENT_SECRET`
245
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
246
+
247
+ ### discord
248
+
249
+ **Discord** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
250
+
251
+ - **Settings:** `DISCORD_CLIENT_ID`, `DISCORD_CLIENT_SECRET`
252
+ - **Where the client comes from:** https://discord.com/developers/applications
253
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/discord`
254
+ - **How it is sent:** POST `discord.com/api/oauth2/token` (the client in the Basic header)
255
+ - **Scope sets an app lists:** none: the whole client is the grant
256
+ - **Set it:** `pnpm everyapp secret set DISCORD_CLIENT_ID DISCORD_CLIENT_SECRET`
257
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
258
+
259
+ ### slack
260
+
261
+ **Slack** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
262
+
263
+ - **Settings:** `SLACK_CLIENT_ID`, `SLACK_CLIENT_SECRET`
264
+ - **Where the client comes from:** https://api.slack.com/apps
265
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/slack`, `https://<app>.<APP_BASE_DOMAIN>/integrations/slack/callback`
266
+ - **How it is sent:** POST `slack.com/api/oauth.v2.access` (the client in the form body)
267
+ - **Scope sets an app lists:** `channels.read`, `users.read`, `users.email`, `messages.write`, `channels.join`, `channels.manage`, `files.write`, `user-channels.manage`
268
+ - **Set it:** `pnpm everyapp secret set SLACK_CLIENT_ID SLACK_CLIENT_SECRET`
269
+ - **Guide:** [slack.md](slack.md)
270
+
271
+ ### mastodon
272
+
273
+ **Mastodon** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
274
+
275
+ - **Settings:** `MASTODON_CLIENT_ID`, `MASTODON_CLIENT_SECRET`, `MASTODON_URL`
276
+ - **Where the client comes from:** `<MASTODON_URL>/settings/applications`
277
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/mastodon`
278
+ - **How it is sent:** POST `<MASTODON_URL>/oauth/token` (the client in the form body)
279
+ - **Scope sets an app lists:** none: the whole client is the grant
280
+ - **Set it:** `pnpm everyapp secret set MASTODON_CLIENT_ID MASTODON_CLIENT_SECRET MASTODON_URL`
281
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
282
+
283
+ ### kick
284
+
285
+ **Kick** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
286
+
287
+ - **Settings:** `KICK_CLIENT_ID`, `KICK_CLIENT_SECRET`
288
+ - **Where the client comes from:** https://kick.com/settings/developer
289
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/kick`
290
+ - **How it is sent:** POST `id.kick.com/oauth/token` (the client in the form body)
291
+ - **Scope sets an app lists:** none: the whole client is the grant
292
+ - **Set it:** `pnpm everyapp secret set KICK_CLIENT_ID KICK_CLIENT_SECRET`
293
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
294
+
295
+ ### twitch
296
+
297
+ **Twitch** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
298
+
299
+ - **Settings:** `TWITCH_CLIENT_ID`, `TWITCH_CLIENT_SECRET`
300
+ - **Where the client comes from:** https://dev.twitch.tv/console/apps
301
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/twitch`
302
+ - **How it is sent:** POST `id.twitch.tv/oauth2/token` (the client in the form body)
303
+ - **Scope sets an app lists:** none: the whole client is the grant
304
+ - **Set it:** `pnpm everyapp secret set TWITCH_CLIENT_ID TWITCH_CLIENT_SECRET`
305
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
306
+
307
+ ### tumblr
308
+
309
+ **Tumblr** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
310
+
311
+ - **Settings:** `TUMBLR_CLIENT_ID`, `TUMBLR_CLIENT_SECRET`
312
+ - **Where the client comes from:** https://www.tumblr.com/oauth/apps
313
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/tumblr`
314
+ - **How it is sent:** POST `api.tumblr.com/v2/oauth2/token` (the client in the form body)
315
+ - **Scope sets an app lists:** none: the whole client is the grant
316
+ - **Set it:** `pnpm everyapp secret set TUMBLR_CLIENT_ID TUMBLR_CLIENT_SECRET`
317
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
318
+
319
+ ### dribbble
320
+
321
+ **Dribbble** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
322
+
323
+ - **Settings:** `DRIBBBLE_CLIENT_ID`, `DRIBBBLE_CLIENT_SECRET`
324
+ - **Where the client comes from:** https://dribbble.com/account/applications
325
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/social/dribbble`
326
+ - **How it is sent:** POST `dribbble.com/oauth/token` (the client in the query)
327
+ - **Scope sets an app lists:** none: the whole client is the grant
328
+ - **Set it:** `pnpm everyapp secret set DRIBBBLE_CLIENT_ID DRIBBBLE_CLIENT_SECRET`
329
+ - **Guide:** none beyond this section; the scopes to allow are in https://everyapp.com/docs/agent/repo/capabilities#oauth-clients
330
+
331
+ ### google-workspace
332
+
333
+ **Google (Gmail, Calendar, Search Console and Analytics)** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
334
+
335
+ - **Settings:** `GOOGLE_WORKSPACE_CLIENT_ID`, `GOOGLE_WORKSPACE_CLIENT_SECRET`
336
+ - **Where the client comes from:** https://console.cloud.google.com/apis/credentials
337
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/google/callback`
338
+ - **How it is sent:** POST `oauth2.googleapis.com/token` (the client in the form body)
339
+ - **Scope sets an app lists:** `identity`, `gmail.read`, `calendar.read`, `search-console.read`, `analytics.read`
340
+ - **Set it:** `pnpm everyapp secret set GOOGLE_WORKSPACE_CLIENT_ID GOOGLE_WORKSPACE_CLIENT_SECRET`
341
+ - **Guide:** [google.md](google.md)
342
+
343
+ ### microsoft-365
344
+
345
+ **Microsoft 365 (Outlook mail and calendar)** (`oauth_client`): the Gateway holds the client and completes the token endpoints only; the app builds the authorize URL from the public client id and keeps people's tokens.
346
+
347
+ - **Settings:** `MICROSOFT_365_CLIENT_ID`, `MICROSOFT_365_CLIENT_SECRET`
348
+ - **Where the client comes from:** https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
349
+ - **Redirect URIs to register:** `https://<app>.<APP_BASE_DOMAIN>/integrations/microsoft/callback`
350
+ - **How it is sent:** POST `login.microsoftonline.com/common/oauth2/v2.0/token` (the client in the form body)
351
+ - **Scope sets an app lists:** `identity`, `mail.read`, `calendar.read`
352
+ - **Set it:** `pnpm everyapp secret set MICROSOFT_365_CLIENT_ID MICROSOFT_365_CLIENT_SECRET`
353
+ - **Guide:** [microsoft-365.md](microsoft-365.md)
@@ -0,0 +1,199 @@
1
+ # A remote MCP server as an MCP app
2
+
3
+ Any remote MCP server that speaks Streamable HTTP (a docs search, a
4
+ company's API, a SaaS tool's MCP endpoint) can become an MCP app of the
5
+ Gateway's: `pnpm everyapp mcp add <url>` registers it, the Gateway serves its
6
+ tools on its own `/mcp` to every member it is granted to as `<id>_<tool>`,
7
+ holds the server's credential itself (a Gateway setting, never sent to an AI
8
+ client), sends it only to the server's origin, and attributes, audits and
9
+ counts every call like an app's. A read-only connection sees only the tools
10
+ whose risk is `read`. At the end the person has the app on, its credential
11
+ set and pinned to the server's origin, the people who need it granted, and
12
+ one tool call through the Gateway's `/mcp` that worked.
13
+
14
+ ## Settings
15
+
16
+ | NAME | required or optional | what it holds |
17
+ | ------------------------------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
18
+ | `<ID>_MCP_TOKEN` (the app id upper-cased, `-` as `_`; `--secret` picks another name ending in `_MCP_TOKEN`) | required, unless the server takes no credential (`--auth none`) | What the server's docs call its API key, token or password. `--auth bearer` sends it as `Authorization: Bearer <value>`; `--auth header --header X-Api-Key` as `X-Api-Key: <value>`; `--auth basic` takes `user:password` and sends HTTP Basic. |
19
+
20
+ The name is a Gateway setting like any provider key, set with
21
+ `pnpm everyapp secret set <NAME>` (any name ending in `_MCP_TOKEN` goes to the
22
+ Gateway; nothing else is accepted for it). When it is set, the CLI pins it to
23
+ the origin of the MCP app that declares it (`https://treg.to` for
24
+ `https://treg.to/mcp/`): the Gateway sends a credential only to the origin it
25
+ was set for. A server re-pointed or re-added at another address needs its
26
+ credential set again; only the operator (the Cloudflare login) can, so an
27
+ owner or admin who changes an app in the Gateway never moves a credential.
28
+ `mcp list` and `mcp show` say "needs setup" until it is set and pinned.
29
+
30
+ `--auth oauth` is accepted and recorded, but the Gateway doesn't sign in to
31
+ MCP servers with OAuth this week: such an app serves no tools ("OAuth: not
32
+ supported yet"). If an OAuth server also takes an API key, add it with
33
+ `--auth bearer` instead.
34
+
35
+ ## Costs and plans
36
+
37
+ Every App charges nothing for an MCP app. The server's provider charges what
38
+ it charges for its calls (its own plan and limits apply; read them on its
39
+ site). Every forwarded call is counted in the organization's usage as
40
+ `mcp:<id>`, and an owner or admin can cap an app's calls per month in Admin →
41
+ Usage (off by default): past the cap a tool answers a tool error naming it
42
+ until the next UTC month.
43
+
44
+ ## Only a person can
45
+
46
+ - Create an account with the server's provider and accept its terms, when it
47
+ has any.
48
+ - Create the API key or token on the provider's dashboard and type it at the
49
+ hidden prompt.
50
+ - Decide who gets the app beyond the owners and admins (Admin → Apps → Manage
51
+ access), and whether a tool the server says is safe should count as a write
52
+ (you suggest; they decide).
53
+ - Decide to replace a credential the Gateway already holds.
54
+
55
+ ## Before you start
56
+
57
+ 1. `pnpm everyapp status --json`: `data.installed` and `data.claimed` are
58
+ true; `data.gatewayUrl` is `https://<gateway host>`. Not installed, or no
59
+ owner: [gateway.md](gateway.md) first.
60
+ 2. The server's MCP address and how it authenticates, from its docs: an
61
+ `https://` URL (often ending in `/mcp`) that speaks Streamable HTTP. An old
62
+ HTTP+SSE-only endpoint (a separate `/sse` URL from 2024) isn't served. The
63
+ credential is usually an API key sent as a bearer token; some servers read
64
+ a header of their own (`X-Api-Key`); public servers take none. The
65
+ Gateway follows no redirects, so use the address the server answers at,
66
+ not one that redirects to it.
67
+ 3. `pnpm everyapp mcp list --json`: the server isn't added already (no entry
68
+ in `data.apps` with its `url`). The id is the domain's name, the label
69
+ before its suffix (`https://mcp.deepwiki.com/mcp` → `deepwiki`,
70
+ `https://treg.to/mcp/` → `treg`), or `--name <id>` (lowercase letters,
71
+ digits and hyphens, at most 32 characters); it is the tools' prefix, so
72
+ keep it short.
73
+
74
+ ## Steps
75
+
76
+ One step per message: give the step, wait for the words it ends with
77
+ ("done", "I have it"), then the next.
78
+
79
+ 1. **You:** add it. `pnpm everyapp mcp add <url> --auth bearer --json` (or
80
+ `--auth header --header <name>`, `--auth basic`; nothing for a public
81
+ server), with `--name <id>` when the host name makes a poor id and
82
+ `--risk read` for a server that only reads and doesn't say so in its tool
83
+ annotations (`--risk write` treats every tool as a write). The app is on
84
+ at once for the person running it (when they are a member), the owners
85
+ and the admins. The `done` event's `data.id`, `data.key` (null for
86
+ `--auth none`; else the credential's `name` and whether it is `set` and
87
+ `bound` to the URL's origin) and `data.probe` (what one look at the server
88
+ from this machine found, without the credential) say what happened.
89
+ `PROVIDER_KEY_UNSET` means the credential comes next.
90
+ `REMOTE_MCP_PROBE_FAILED` and `REMOTE_MCP_WANTS_OAUTH` are warnings, never
91
+ refusals: a 401 with `--auth none` means the server wants a credential
92
+ (`pnpm everyapp mcp remove <id>`, then the same add with `--auth bearer`), a
93
+ redirect means another address, and "Couldn't reach" may be this
94
+ machine's network only (the Gateway fetches from Cloudflare).
95
+ 2. **Person:** the credential. They create the key on the provider's
96
+ dashboard, then, in a second terminal in the `every-app` folder:
97
+ `pnpm everyapp secret set <NAME>` (the name from step 1, for example
98
+ `pnpm everyapp secret set TREG_MCP_TOKEN`) and paste it at the hidden
99
+ prompt (for `--auth basic`, `user:password`). It ends with
100
+ `Set <NAME> on the Gateway`. When the person runs `mcp add` themselves at
101
+ a terminal, it asks `Set <NAME> now?` right after adding and, on yes, shows
102
+ the same hidden prompt (`secret set`'s own); No leaves it for `secret set`.
103
+ The README's other two ways work as for any `secret set` (a pipe into
104
+ `pnpm everyapp secret set <NAME> --json`, or the hidden read then
105
+ `--from-env <VAR>`); `mcp add <url> --auth bearer --from-env <VAR> --json`
106
+ takes the variable at the add itself, read before anything is written.
107
+ Wait for "done".
108
+ 3. **Person:** who gets it. The owners, the admins and whoever added it have
109
+ it already. Anyone else: Admin → Apps → the app's row → **Manage access**.
110
+ A member sees its tools after granting, in a client connected to the
111
+ Gateway (the next step).
112
+ 4. **Person:** connect an AI client to the Gateway if theirs isn't yet:
113
+ `claude mcp add --transport http everyapp https://<gateway host>/mcp`,
114
+ then `/mcp` → **everyapp** → **Authenticate** in Claude Code (other clients:
115
+ the same URL; mcp.md beside this folder, "Connecting a person").
116
+
117
+ ## Verify
118
+
119
+ 1. `pnpm everyapp mcp show <id> --json`: `data.status` is `"on"` (not
120
+ `"needs setup"`), `data.key.set` and `data.key.bound` are true and
121
+ `data.key.boundOrigin` is the URL's origin (all three skipped for
122
+ `--auth none`: `data.key` is null). `data.snapshot` is null until the
123
+ Gateway lists the tools, on the first request to its `/mcp` after the add
124
+ (or within the hour). From the checkout root,
125
+ `pnpm everyapp secret list --json` agrees: the name is in
126
+ `data.gateway.names`, its `data.gateway.mcpCredentials` entry has
127
+ `set: true`, and the app has left `data.apps` (it is listed there only
128
+ while it needs setup, with `setup.command` the `secret set` that sets it
129
+ up).
130
+ 2. One tool call through the Gateway: in the person's connected client, ask
131
+ for something the server does ("use <id> to …", or "list the tools <id>
132
+ offers"); the client shows a call to an `<id>_<tool>` tool and its
133
+ answer. On a Gateway with many tools the client may list them compactly:
134
+ then it finds them with `everyapp_search_tools` (`{ "app": "<id>" }`) and
135
+ runs one through `everyapp_call_read`. Then
136
+ `pnpm everyapp mcp show <id> --json` again: `data.snapshot.tools` is the
137
+ count listed and `data.tools[]` has each with its `name`, `serverName`,
138
+ `risk` and `source` (`hint`: the server's annotation; `default`: no
139
+ annotation, counted as a write; `app`: the `--risk` default;
140
+ `override`: yours).
141
+ 3. Risks, with the person: a tool the server marks read-only is callable by
142
+ every connection; one without a hint is a write (hidden from read-only
143
+ connections); one marked destructive is hidden from every client until
144
+ approvals exist. Change one with
145
+ `pnpm everyapp mcp tool <id> <tool> --risk read|write|destructive --json`
146
+ (`--risk annotations` drops the override), or leave a tool out entirely
147
+ with `--off`; the Gateway lists the tools again on first use.
148
+ 4. Logs, when a call fails: README's path (**Workers & Pages** →
149
+ `every-app-gateway` → **Observability** → **Live**). The remote proxy logs
150
+ each failed upstream call as `mcp.remote.upstream_failed` with the status
151
+ (never the credential), and a first-use pin as
152
+ `mcp.remote.credential_bound` (names from the design,
153
+ docs/design/2026-10-mcp-by-url.md; not checked against a live Gateway
154
+ here, unverified).
155
+
156
+ ## If it fails
157
+
158
+ | error or symptom | meaning | what to do |
159
+ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
160
+ | `SECRET_VALUE_REQUIRED` from `secret set --json` | Nothing was piped and there is no terminal to prompt in | One of the README's three ways: the person's own terminal, a pipe, or `--from-env` |
161
+ | `SECRET_EMPTY` | The `--from-env` variable is empty or not exported in that shell (from `mcp add --from-env`, nothing was added) | The hidden read (README's third way) in that same terminal first, then rerun |
162
+ | `REMOTE_MCP_URL_REFUSED` | Not `https://`, an IP address, the Gateway's own host or app domain, or a provider the Gateway holds a key for | The server's own MCP address, by host name, over https |
163
+ | `REMOTE_MCP_EXISTS` | That id is an MCP app already | `pnpm everyapp mcp show <id>`; another address is `mcp remove <id>` then `mcp add` again, or another `--name` |
164
+ | `REMOTE_MCP_SECRET_TAKEN` | Another MCP app at another origin uses that credential name | `--secret <OTHER>_MCP_TOKEN`: one credential name per origin |
165
+ | `REMOTE_MCP_INVALID` | A bad id, risk, header or credential name, or flags that say two things | As the message says |
166
+ | `PROVIDER_APP_UNKNOWN` | The id isn't an MCP app here | `pnpm everyapp mcp list` for the ids |
167
+ | `REMOTE_MCP_SECRET_BOUND_ELSEWHERE` from `mcp add`, or `needs setup` in `mcp list` or `mcp show` with the key set | The credential is pinned to another origin (`data.key.boundOrigin`): it was set for an earlier server | `pnpm everyapp secret set <NAME>` again (Steps 2) |
168
+ | `REMOTE_MCP_TOOL_NOT_LISTED` from `mcp tool` | The tool's name isn't in the last listing: the override was kept under that name, as the server's | `pnpm everyapp mcp show <id>` for both names, then `mcp tool` with the right one |
169
+ | `REMOTE_MCP_SECRET_UNDECLARED` from `secret set` | No MCP app declares that name (a typo, or set before `mcp add`) | Check the name with `mcp show <id>`; `mcp add` first |
170
+ | `REMOTE_MCP_WANTS_OAUTH` | The server wants OAuth, which the Gateway doesn't do yet | If it also takes an API key: `--auth bearer` and set the key; otherwise it can't be served this week |
171
+ | `REMOTE_MCP_GATEWAY_OUTDATED` | The Gateway predates MCP apps by URL | `pnpm everyapp update`, then Verify |
172
+ | `data.snapshot.status` `error`, `lastError` naming 401 | The server rejected the credential | A fresh key from the provider, `secret set` again, then `pnpm everyapp mcp refresh <id>` |
173
+ | `lastError` naming a redirect or a timeout | The address redirects, or the server is slow or down | The address it redirects to (remove, add again); a slow server: retry later |
174
+ | The tools changed on the server, not on the Gateway | The Gateway's snapshot is up to an hour old | `pnpm everyapp mcp refresh <id>` |
175
+ | A tool is missing for one person only | Their connection is read-only (write tools hidden), or they weren't granted the app | Admin → Apps → Manage access; a read & write connection |
176
+
177
+ ## Rerun, rotate, remove
178
+
179
+ - **Rerun.** `mcp add` refuses an id that exists (`REMOTE_MCP_EXISTS`), so a
180
+ rerun starts from Verify. `secret set` replaces; `mcp tool` and
181
+ `mcp refresh` can run again.
182
+ - **Rotate.** A new key on the provider's dashboard, then Steps 2 again: the
183
+ Gateway uses the new value on its next request. A value that went through
184
+ the chat is compromised: rotate it.
185
+ - **Off, and back on.** `pnpm everyapp mcp off <id> --json` stops serving it
186
+ and keeps everyone's access, tokens and the snapshot;
187
+ `pnpm everyapp mcp on <id> --json` serves it again at once.
188
+ - **Remove.** `pnpm everyapp mcp remove <id> --json`: a tombstone, with
189
+ everyone's access, its tokens and its place in AI connections gone (adding
190
+ it again starts fresh). The credential and its pin stay;
191
+ `pnpm everyapp secret unset <NAME> --json` removes both (it asks; with
192
+ `--json` add `--yes` only once the person said so). Then revoke the key on
193
+ the provider's side.
194
+
195
+ ## Sources
196
+
197
+ - docs/design/2026-10-mcp-by-url.md (the remote block, the credential family and its pin, the proxy, the defaults taken)
198
+ - In code: `packages/sdk/src/internal/remoteMcp.ts` (the URL, id, auth and risk rules: `remoteMcpUrlProblem`, `remoteMcpIdFromUrl`, `remoteToolRisk`), `packages/sdk/src/internal/gatewaySettings.ts` (`isRemoteMcpSecretName`: any name ending in `_MCP_TOKEN` is the Gateway's), `packages/sdk/src/internal/appSettings.ts` (the `remote-mcp` setting kind naming this file), `packages/perimeter/src/registry/remoteMcpApps.ts` (`planRemoteMcpAppAdd` and its refusals), `packages/cli/src/commands/provider/index.ts` (`mcp add`, `show`, `tool`, the probe's warnings), `packages/cli/src/lib/gateway/remoteMcpApps.ts` (the rows, the pin in `remote_mcp_credentials`), `packages/cli/src/commands/secret/index.ts` (the pin on `secret set`, dropped on `secret unset`), `apps/every-app-gateway/src/db/remote-mcp.schema.ts` (migration 0011)
199
+ - https://modelcontextprotocol.io/specification (Streamable HTTP transport, tool annotations `readOnlyHint` and `destructiveHint`, authorization with `resource_metadata`)