@everfur/cli 0.2.0 → 0.4.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.
- package/README.md +122 -47
- package/dist/{chunk-S6UN7D2O.js → chunk-2MTX6YWO.js} +74 -30
- package/dist/{chunk-TBFOL2D3.js → chunk-A2QEBO5U.js} +1 -1
- package/dist/{chunk-CEWWBPPT.js → chunk-EBVP6FAD.js} +5638 -990
- package/dist/{chunk-WCH6AI6K.js → chunk-QCXZJW5C.js} +663 -227
- package/dist/{chunk-VHZWTB6J.js → chunk-YRGSY4R2.js} +81 -14
- package/dist/everfur-mcp-hosted.js +4 -4
- package/dist/everfur-mcp-http.js +3 -3
- package/dist/everfur-mcp.js +2 -2
- package/dist/everfur.js +2 -2
- package/dist/index.d.ts +420 -113
- package/dist/index.js +2 -2
- package/package.json +4 -3
- package/schema/error-explanation.v1.schema.json +26 -4
- package/schema/plan.v1.schema.json +49 -4
- package/schema/verification.v1.schema.json +5 -4
- package/dist/everfur-mcp-container.d.ts +0 -2
- package/dist/everfur-mcp-container.js +0 -60
package/README.md
CHANGED
|
@@ -14,9 +14,14 @@ template) includes a 2 KB loader and gets the chat in an iframe on Everfur's ori
|
|
|
14
14
|
a Shopify theme or app gets the Everfur app's `Everfur chat` block, with Shopify vouching for the
|
|
15
15
|
signed-in customer so no backend mints. `--embedding in-page|frame` overrides the detected embedding.
|
|
16
16
|
A capability the web cannot render (photo in the page, anything but chat in the frame) is reported as
|
|
17
|
-
blocked by the platform, beside the steps for the rest.
|
|
18
|
-
adds the checks a
|
|
19
|
-
browser depends on, the tenant's session policy, and the loader
|
|
17
|
+
blocked by the platform, beside the steps for the rest. For a page that includes the loader,
|
|
18
|
+
`everfur verify --origin https://your.page --embedding frame` adds the checks a framed page needs: the embed
|
|
19
|
+
allowlist for that origin, the CORS exposure a browser depends on, the tenant's session policy, and the loader
|
|
20
|
+
of the key's environment. An in-page integration calls the API from its own origin, so it passes `--origin` too, with
|
|
21
|
+
`--embedding in-page`: the preflight is of a widget request with the headers the SDK sends, the exposure and the
|
|
22
|
+
session policy are checked, and the embed fence and the loader, which it never uses, are reported `N/A` rather than
|
|
23
|
+
failed. Only a named `--embedding in-page` does that: with none named every check runs, and a project whose page
|
|
24
|
+
includes the Everfur loader is checked as the frame it embeds.
|
|
20
25
|
|
|
21
26
|
**The generated surface matches your own theme when the plan can read it, and says so when it cannot.** The
|
|
22
27
|
plan reads, statically and never by executing anything, a Tailwind v4 `@theme` block, a `tailwind.config.{js,ts}`
|
|
@@ -37,14 +42,22 @@ config that runs code when it loads) is low: no theme is written, and the step n
|
|
|
37
42
|
offers the manual `theme={{ ... }}` snippet. Over a remote MCP pass the config or CSS text as `theme_source`. The
|
|
38
43
|
tenant's console branding is merged with the emitted theme per field (a locked field keeps the console's value;
|
|
39
44
|
the console fills what the theme leaves unset); the plan holds no branding credential and never changes it.
|
|
45
|
+
Branding v2 (SDK 0.9.0): a success, warning or info colour and a heading stack the theme declares by name
|
|
46
|
+
(`--success`, `--color-warning`, `--font-heading`, `--font-display`, Tailwind v3 `colors.info` or
|
|
47
|
+
`fontFamily.heading`) are written too, as `successColor`, `warningColor`, `infoColor` (with their dark twins) and
|
|
48
|
+
`headingFontFamily`; a theme that declares none gets none. The logo and the chat's assistant avatar are uploaded in
|
|
49
|
+
the partner console, the only images the SDK shows, so a logo read from the project is named as the image to upload
|
|
50
|
+
rather than written. Custom fonts apply in-page only: the hosted frame keeps Everfur's fonts.
|
|
40
51
|
|
|
41
52
|
**The chat and records mounts match the Everfur app, and the host seams are generated with them.** Chat has the
|
|
42
53
|
header pet switcher (it appears by itself once two or more pets are registered), quick prompts, citations, thumbs
|
|
43
54
|
feedback, the urgency banner and the history drawer built in. On an emergency or schedule-soon reply the banner's
|
|
44
55
|
Find a vet pill opens the Everfur vet visit entry when Everfur has it on for your client, else calls `onFindVet`, else
|
|
45
|
-
does not render
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
does not render. No generated mount passes `onFindVet`, so the plan writes no vet finder of its own that sends the
|
|
57
|
+
member to a page outside your app; the commented `onFindVet` line beside each in-page chat mount is for an app with
|
|
58
|
+
its own in-app vet finder (on React Native, passing it also replaces the Everfur vet entry on the check-in card). A
|
|
59
|
+
frame takes no `onFindVet`,
|
|
60
|
+
so there the pill appears only while Everfur has its vet visit entry on for your client. The SDK bundles no picker and no
|
|
48
61
|
clipboard module, so an EXPO plan mounts `<EverfurChat attachments={{ pick: pickChatPhoto }}
|
|
49
62
|
onCopy={copyText} />` and writes both helpers into `everfur/EverfurRoot.tsx`, the module the app mounts from its
|
|
50
63
|
own entry (`app/_layout.tsx` in an Expo Router app, `App.tsx` otherwise): in an Expo app `pickChatPhoto` opens the system
|
|
@@ -70,24 +83,52 @@ because it asked for one) and always carries the size when the picker reports it
|
|
|
70
83
|
records upload, so no image picker is wired there. The system document UI is not the media library and needs no
|
|
71
84
|
permission on either platform, so unlike the chat photo picker there is nothing to request before it opens. On the web the
|
|
72
85
|
browser is the picker and the speech engine: photo attachments and voice dictation are on by default, and
|
|
73
|
-
`attachments={false}` and `dictation={false}` turn them off.
|
|
74
|
-
opens on the pet's dashboard and owns its own stack (the hardware back key pops it),
|
|
75
|
-
name
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
`attachments={false}` and `dictation={false}` turn them off. On React Native records is the app's screen flow:
|
|
87
|
+
`<EverfurRecords>` opens on the pet's dashboard and owns its own stack (the hardware back key pops it), and
|
|
88
|
+
`initialScreen={{ name: 'request', requestId }}` opens a request directly, which is what the generated notification
|
|
89
|
+
router's `record_request` handler says to do. On the web records is a page, the shape of Everfur's own web records
|
|
90
|
+
page: the generated `EverfurRecordsSurface` renders `EverfurRecordsPage` and opens what it links to (the full record,
|
|
91
|
+
the timeline, an upload) in the records flow in the same place, with no route added to your app; the page holds no clinic
|
|
92
|
+
request of its own, so `records-clinic` mounts beside it. Every screen is exported by name for your own navigator,
|
|
93
|
+
and the plan's `mount-records-screens` step names them per platform. The mount passes `petName={selectedPet.name}` for
|
|
94
|
+
headings such as `{petName}'s lab trends` (and `onCopy={copyText}` on React Native, for the share sheet). An Expo
|
|
95
|
+
records mount also passes `onOpenUrl={openRecordUrl}`, which handles the share sheet the way the Everfur app does: a
|
|
96
|
+
share link goes to the OS share sheet, and the record PDF is downloaded into the app's cache (`expo-file-system`),
|
|
97
|
+
shared as a file (`expo-sharing`) and deleted, so neither opens a browser. A bare React Native mount passes none, and
|
|
98
|
+
the SDK's default opens both in the system browser until you pass your own. Lab markers, share links, the record PDF link, fact
|
|
79
99
|
edits and the signature gallery need the platform flag `partner.records_full_depth_enabled`; while it is off the
|
|
80
100
|
SDK hides them.
|
|
81
101
|
|
|
82
|
-
**
|
|
102
|
+
**The vet visit runs inside your app.** A plan that mounts `televet` installs `@everfur/sdk@^0.9.0`, a release
|
|
103
|
+
whose `VetVisitButton`, `useVetVisit().open()` and `openVisit()`, and every vet entry inside chat open the visit in
|
|
104
|
+
the app by default, and writes the two things that default needs: `registerEverfurDaily(...)` once at load, from
|
|
105
|
+
`@everfur/sdk/televet/call` over `@daily-co/react-native-daily-js` (React Native) or from
|
|
106
|
+
`@everfur/sdk/web/televet/call` over `import('@daily-co/daily-js')` (the web), and one `<EverfurTelevetHost />`
|
|
107
|
+
inside the provider, where every visit opens: a full-screen modal on React Native, a dialog in the SDK's own DOM
|
|
108
|
+
subtree on the web. The button passes no `returnTo` and no `prefer`, the file registers no presenter and reads no
|
|
109
|
+
return URL, and the chat mount gets the member's state as `vetUsState`. On React Native the plan installs the Daily
|
|
110
|
+
modules the consumer app runs and the native setup (the Expo config plugin and a clean prebuild, or the bare
|
|
111
|
+
manifest and Info.plist edits), and the notifications file opens a tapped visit in the app through the same hook.
|
|
112
|
+
The booking lists vets only for the member's US state and the SDK never reads a device location, so the file's
|
|
113
|
+
`YOUR_USER_US_STATE` reaches the button, the chat and the notifications bridge, and `everfur verify --project-root`
|
|
114
|
+
fails while it is still `null` as shipped. The hosted visit in the system browser or a new tab is the SDK's explicit
|
|
115
|
+
`prefer="redirect"`, which no generated file passes. A plan without `televet` installs the same `@everfur/sdk@^0.9.0`
|
|
116
|
+
and none of the call.
|
|
117
|
+
|
|
118
|
+
<!-- Owner-approved 2026-10-01 (production sandbox plan, PC-1/PC-2): what `test` and the key prefixes mean. -->
|
|
119
|
+
**Every plan that writes code names its environment.** `--environment test|staging|production` (or
|
|
83
120
|
`environment` over MCP) is required and never assumed; generated files read the publishable key and base
|
|
84
121
|
URL from the framework's own variables (`NEXT_PUBLIC_`, `VITE_`, `EXPO_PUBLIC_`) and the plan writes the
|
|
85
|
-
names into `.env.example`.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
122
|
+
names into `.env.example`. `test` is your **sandbox tenant on the production API**
|
|
123
|
+
(`https://api.everfur.com/api/v1`), issued a `pk_test_` key, whose entitlements report `livemode: false`;
|
|
124
|
+
`staging` is your sandbox tenant on the staging API (`https://api-staging.everfur.com/api/v1`), for early
|
|
125
|
+
access; `production` is your live tenant and its `pk_live_` key. The key prefix names the tenant mode: a
|
|
126
|
+
sandbox created before `pk_test_` keys were issued may still carry `pk_live_`. The web framework is detected from the project: the Next.js App Router gets a
|
|
89
127
|
`'use client'` surface and a Route Handler, the Pages Router a component and an API route, Vite with React
|
|
90
|
-
reads `import.meta.env
|
|
128
|
+
reads `import.meta.env` and gets `server/dev-server.ts`, a development server for its session route (a Vite build has
|
|
129
|
+
no server, so the plan also says where the route goes in production). A signed-in React Native app gets the same server
|
|
130
|
+
on its own route, with the URL that reaches it from the iOS simulator, the Android emulator and a device, and its
|
|
131
|
+
server-only names in `server/.env.example`, never in the app's env file. `everfur verify --surfaces chat,records,televet,theme` exercises each surface
|
|
91
132
|
with the minted session (Televet mints a handoff only on a sandbox tenant, and a surface Everfur has not
|
|
92
133
|
switched on is reported `GATED`, not failed); `--project-root <path>` adds offline checks for a secret key
|
|
93
134
|
in source or client build output and for `'use client'`. `everfur diagnose --bundle` prints one support
|
|
@@ -95,20 +136,40 @@ document with no credential value in it.
|
|
|
95
136
|
|
|
96
137
|
## The fastest path: let your agent do it
|
|
97
138
|
|
|
98
|
-
### Hosted MCP: nothing to
|
|
139
|
+
### Hosted MCP: nothing to install
|
|
99
140
|
|
|
100
|
-
Everfur runs the MCP server for you
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
141
|
+
Everfur runs the MCP server for you, so there is no key, token, variable or file to set. It is reachable at
|
|
142
|
+
two endpoints, one per deployment:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
https://mcp.everfur.com/mcp production: your sandbox (test) tenant and your live tenant
|
|
146
|
+
https://mcp-staging.everfur.com/mcp staging: an early-access sandbox tenant on the staging API
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Use the one for the deployment your tenant is on. A client pointed at the other one signs in to a different
|
|
150
|
+
deployment and does not fall back to anything.
|
|
151
|
+
|
|
152
|
+
Add the URL to your editor as a remote (Streamable HTTP) MCP server. You paste the URL yourself; there is
|
|
153
|
+
nothing to search for in a connector directory. Adding it is the whole configuration step:
|
|
104
154
|
|
|
105
155
|
- **Claude Code:** `claude mcp add --transport http everfur https://mcp.everfur.com/mcp`
|
|
106
156
|
- **Cursor:** `.cursor/mcp.json` with `{"mcpServers":{"everfur":{"url":"https://mcp.everfur.com/mcp"}}}`
|
|
107
157
|
- **VS Code:** `.vscode/mcp.json` with `{"servers":{"everfur":{"type":"http","url":"https://mcp.everfur.com/mcp"}}}`
|
|
108
158
|
- **Codex:** a streamable HTTP server entry with that URL in `~/.codex/config.toml` (`[mcp_servers.everfur]`, `url`)
|
|
109
|
-
- **claude.ai:** a custom connector
|
|
110
|
-
|
|
111
|
-
|
|
159
|
+
- **claude.ai:** add it as a **custom connector** at <https://claude.ai/customize/connectors> (**+**, then
|
|
160
|
+
**Add custom connector**): name it `Everfur` and paste the URL exactly, all lowercase, `https://`, `/mcp` on
|
|
161
|
+
the end, no trailing slash. Leave **Request headers** empty: Everfur never wants a key there. Click
|
|
162
|
+
**Connect** and sign in to the partner console. The approval page names Claude as the application asking
|
|
163
|
+
and shows the address Claude will be sent back to, `https://claude.ai/api/mcp/auth_callback` or
|
|
164
|
+
`https://claude.com/api/mcp/auth_callback`; anything else is not Everfur's consent page. Connecting does not
|
|
165
|
+
switch it on for every conversation: in a chat, **+**, then **Connectors**, then toggle **Everfur**. To check
|
|
166
|
+
it worked, ask Claude to explain the Everfur error code `authExpired`: an answer through
|
|
167
|
+
`everfur_explain_error` means the connection itself is good.
|
|
168
|
+
|
|
169
|
+
There is no key to type because the server authenticates you instead. On first connect it answers with a
|
|
170
|
+
`401` naming its OAuth resource metadata, your client registers itself automatically (dynamic client
|
|
171
|
+
registration, RFC 7591), and you are sent to the Everfur partner console to sign in and approve. From then
|
|
172
|
+
on every tool runs as the tenant of that console session.
|
|
112
173
|
|
|
113
174
|
The tools are the same five as below, plus eight that read your own tenant, with these differences that follow
|
|
114
175
|
from where the server runs:
|
|
@@ -134,8 +195,7 @@ from where the server runs:
|
|
|
134
195
|
`everfur_list_webhook_deliveries`, `everfur_get_webhook_delivery`, `everfur_list_events`,
|
|
135
196
|
`everfur_get_usage_summary`, `everfur_get_records_status_summary` and `everfur_search_docs` (the error
|
|
136
197
|
registry, capabilities and guide of your contract). None returns a signing secret, a key value or a
|
|
137
|
-
member's content.
|
|
138
|
-
[docs/HOSTED_TENANT_API.md](docs/HOSTED_TENANT_API.md).
|
|
198
|
+
member's content.
|
|
139
199
|
|
|
140
200
|
Everything below is for running the server yourself, which is what you want when the agent runs beside the
|
|
141
201
|
project (so `project_root` works) or when your organisation keeps its own MCP process.
|
|
@@ -173,8 +233,8 @@ The four values, and where they come from:
|
|
|
173
233
|
|
|
174
234
|
| Variable | What it is |
|
|
175
235
|
|---|---|
|
|
176
|
-
| `EVERFUR_API_BASE_URL` | The
|
|
177
|
-
| `EVERFUR_PARTNER_KEY` | The sandbox tenant's publishable key
|
|
236
|
+
| `EVERFUR_API_BASE_URL` | The API of your sandbox tenant while you build: `https://api.everfur.com/api/v1` for a test (production sandbox) tenant, the staging API for an early-access one. Going live uses `https://api.everfur.com/api/v1`. |
|
|
237
|
+
| `EVERFUR_PARTNER_KEY` | The sandbox tenant's publishable key, `pk_test_...` (a sandbox created before `pk_test_` keys may still carry `pk_live_`); its entitlements report `livemode: false`. |
|
|
178
238
|
| `EVERFUR_DOCS_KEY` | A read-only docs key (`dk_partner_...`) that opens `GET /partners/contract` and nothing else. |
|
|
179
239
|
| `EVERFUR_SESSION_TOKEN` | A short-lived session your backend minted for a test user. Only `everfur_verify_integration` reads it. |
|
|
180
240
|
|
|
@@ -183,8 +243,10 @@ live changes every value in the block: the production base URL, and the producti
|
|
|
183
243
|
key and docs key (its secret key changes on your backend at the same time). Production keys are issued only
|
|
184
244
|
after `everfur_verify_integration` passes on the sandbox tenant.
|
|
185
245
|
|
|
186
|
-
`EVERFUR_DOCS_KEY` is required
|
|
187
|
-
|
|
246
|
+
`EVERFUR_DOCS_KEY` is required here, for the server you run yourself. The Everfur-hosted connector above
|
|
247
|
+
needs no docs key: it signs in with OAuth and is served the contract as your tenant. The Everfur contract
|
|
248
|
+
(the error registry, capability packs, credential shapes and the decision trees the planner walks) is not
|
|
249
|
+
included in this package: the tools fetch it from
|
|
188
250
|
`GET /partners/contract` on `EVERFUR_API_BASE_URL`, presenting a partner docs key (`dk_partner_...`), and
|
|
189
251
|
cache it on disk (see [Credentials](#credentials)). A partner admin mints a docs key with
|
|
190
252
|
`POST /api/v1/partners/docs-keys` (list with `GET`, revoke with `DELETE /api/v1/partners/docs-keys/{key_id}`);
|
|
@@ -217,7 +279,12 @@ answer, naming each one:
|
|
|
217
279
|
Node backend gets the files; any other backend gets the recipe.
|
|
218
280
|
|
|
219
281
|
That is three questions for an anonymous integration and four for `partner-user-ref`. Once answered, the
|
|
220
|
-
plan's steps include the complete integration file, ready to write.
|
|
282
|
+
plan's steps include the complete integration file, ready to write. Over MCP the tool first returns a small
|
|
283
|
+
summary with a `plan_id` and a number of `pages` (the goal, the detected facts, each step's id, title, one-line
|
|
284
|
+
intent and page, and the checklist); the same call with `plan_id` and `page` returns that page's steps in full,
|
|
285
|
+
commands and file bodies included, and page 1 also the detection, warnings and checklist in full. `steps`
|
|
286
|
+
(step ids) in place of `page` still returns those steps, a page at a time. `everfur plan` prints the whole plan at
|
|
287
|
+
once.
|
|
221
288
|
|
|
222
289
|
The explicit `everfur-mcp` command is intentional: `@everfur/mcp` also ships `everfur-mcp-http` for a
|
|
223
290
|
server deployment, so bare `npx @everfur/mcp` can no longer safely guess which executable you mean.
|
|
@@ -228,7 +295,7 @@ For a partner-operated cloud/server deployment, run the guarded Streamable HTTP
|
|
|
228
295
|
|
|
229
296
|
```bash
|
|
230
297
|
export EVERFUR_API_BASE_URL="https://api-staging.everfur.com/api/v1"
|
|
231
|
-
#
|
|
298
|
+
# The publishable key of a tenant created as a sandbox (pk_test_..., or pk_live_... on an older staging sandbox).
|
|
232
299
|
export EVERFUR_PARTNER_KEY="pk_live_..."
|
|
233
300
|
export EVERFUR_DOCS_KEY="dk_partner_..."
|
|
234
301
|
# For verification only: a short-lived session your backend minted. The server never reads the secret key.
|
|
@@ -245,14 +312,14 @@ put either secret in an agent prompt, a browser, or a client bundle. The HTTP pr
|
|
|
245
312
|
scale behind a load balancer. It does **not** replace a platform OAuth service: use this mode when one
|
|
246
313
|
partner owns the deployment and its credentials.
|
|
247
314
|
|
|
248
|
-
For release gates, reverse-proxy requirements, negative tests, and the staged production rollout, use the
|
|
249
|
-
[remote MCP staging and production runbook](docs/REMOTE_MCP_STAGING_PRODUCTION_RUNBOOK.md).
|
|
250
|
-
|
|
251
315
|
Five tools are served: `everfur_plan_integration`, `everfur_verify_integration`, `everfur_diagnose`,
|
|
252
316
|
`everfur_explain_error`, and `everfur_send_test_message`. Each is a body of the CLI, so the two surfaces
|
|
253
317
|
answer the same question the same way. `everfur_explain_error` is the one to reach for when a response
|
|
254
|
-
carries an error code: it needs no project, reads the registry from the fetched contract,
|
|
255
|
-
|
|
318
|
+
carries an error code: it needs no project, reads the registry from the fetched contract, answers offline the SDK's
|
|
319
|
+
own codes (`EverfurError` and its closed sub-enums such as `AttachmentErrorCode` and `VetVisitErrorReason`), the
|
|
320
|
+
diagnostics reason codes, the CLI's own error codes and the `error.code` these tools return (`VERIFICATION_FAILED`,
|
|
321
|
+
`PLAN_CHANGED` and the rest), and refuses a code it does not recognise instead of explaining it from the shape of the
|
|
322
|
+
string. `everfur explain-error` gives the same answers.
|
|
256
323
|
|
|
257
324
|
Every tool declares an `outputSchema` and returns `structuredContent`. A failed call carries one envelope
|
|
258
325
|
whatever the tool: `error.code`, `error.retryable`, `error.next_action` (a closed vocabulary),
|
|
@@ -275,7 +342,7 @@ npx -y -p @everfur/cli everfur plan
|
|
|
275
342
|
|
|
276
343
|
Plain `npx @everfur/cli` does not work, and the error it gives ("could not determine executable to
|
|
277
344
|
run") does not explain why: this package ships four binaries, `everfur`, `everfur-mcp`,
|
|
278
|
-
`everfur-mcp-http` and `everfur-mcp-hosted` (the entry Everfur runs
|
|
345
|
+
`everfur-mcp-http` and `everfur-mcp-hosted` (the entry Everfur runs itself), and npx only
|
|
279
346
|
picks a binary on its own when there is exactly one, or when one is named after the package. `-p` names
|
|
280
347
|
the package and the word after it names the binary.
|
|
281
348
|
|
|
@@ -288,7 +355,7 @@ the package and the word after it names the binary.
|
|
|
288
355
|
| `everfur diagnose` | Explain why each capability is or is not available to this caller. |
|
|
289
356
|
| `everfur explain-error` | Explain an API error code: cause, retryability, and next action. Reads the registry from `--contract <file>` when given, otherwise from the contract fetched with `EVERFUR_DOCS_KEY`. |
|
|
290
357
|
| `everfur contract validate` | Validate a contract-public projection: envelope shape, then digest. |
|
|
291
|
-
| `everfur sandbox create` |
|
|
358
|
+
| `everfur sandbox create` | Everfur-internal (requires an admin token): mints a partner secret key and, because no claim flow exists to hand it over safely, revokes it again and exits `8`. |
|
|
292
359
|
|
|
293
360
|
`--json` on any command emits a machine-readable document on stdout, which is what you want in CI.
|
|
294
361
|
|
|
@@ -300,7 +367,7 @@ CI is invited to branch on these. An existing code never changes meaning.
|
|
|
300
367
|
|---|---|---|
|
|
301
368
|
| `0` | OK | The command produced a complete answer. |
|
|
302
369
|
| `1` | INTERNAL_ERROR | A bug in the CLI, or an unreadable filesystem. |
|
|
303
|
-
| `2` | USAGE_ERROR | Malformed invocation: unknown command or flag, missing flag value. |
|
|
370
|
+
| `2` | USAGE_ERROR | Malformed invocation: unknown command or flag, missing flag value, or an argument value the command does not recognise (for example `explain-error <unknown code>`). |
|
|
304
371
|
| `3` | UNDERSPECIFIED | The CLI refused to guess. Required facts were missing; supply them and retry. |
|
|
305
372
|
| `4` | INVALID_CONTRACT | A named artifact was missing, unparseable, or failed schema validation. |
|
|
306
373
|
| `5` | DIGEST_MISMATCH | A loaded artifact was well shaped but its digest did not match its content. |
|
|
@@ -308,6 +375,7 @@ CI is invited to branch on these. An existing code never changes meaning.
|
|
|
308
375
|
| `7` | VERIFICATION_FAILED | `verify` ran and at least one hard assertion failed. |
|
|
309
376
|
| `8` | SECRET_UNCLAIMABLE | `sandbox create` minted a key but no claim flow exists to hand it over safely. |
|
|
310
377
|
| `9` | BLOCKED | Nothing you asked for can be built today: the contract blocks every capability you named, or the SDK ships no entry point for this project shape. |
|
|
378
|
+
| `10` | CONTRACT_CREDENTIAL_MISSING | The command needs the Everfur contract and has none: no `--contract` file, no `EVERFUR_CONTRACT_PUBLIC`, and no `EVERFUR_DOCS_KEY` to fetch it with. The error says where a docs key comes from, and that the Everfur-hosted MCP connector (OAuth) needs none. |
|
|
311
379
|
|
|
312
380
|
---
|
|
313
381
|
|
|
@@ -339,7 +407,7 @@ with no network call and no credential.
|
|
|
339
407
|
| Variable | Used for |
|
|
340
408
|
|---|---|
|
|
341
409
|
| `EVERFUR_API_BASE_URL` | Everything that touches the network. No default host. |
|
|
342
|
-
| `EVERFUR_PARTNER_KEY` | Your publishable key (`pk_live_...`). Identifies your tenant.
|
|
410
|
+
| `EVERFUR_PARTNER_KEY` | Your publishable key (`pk_test_...` or `pk_live_...`). Identifies your tenant. The prefix names the tenant mode: `pk_test_` for a sandbox tenant, `pk_live_` for a live one; a sandbox created before `pk_test_` keys may still carry `pk_live_`. |
|
|
343
411
|
| `EVERFUR_PARTNER_SECRET_KEY` | Session minting, server side only. Never ship it in an app, and never put it in an MCP server's environment. `everfur verify` mints with it locally only when `EVERFUR_SESSION_TOKEN` is not set. |
|
|
344
412
|
| `EVERFUR_SESSION_TOKEN` | A short-lived session your backend minted. `everfur verify` and `everfur_verify_integration` use it instead of minting (the MCP tool verifies only this way); `everfur diagnose` uses it for the signed path. |
|
|
345
413
|
| `EVERFUR_DOCS_KEY` | Your partner docs key (`dk_partner_...`). Fetches the contract; accepted by no other route. Minted with `POST /api/v1/partners/docs-keys`. |
|
|
@@ -350,10 +418,11 @@ with no network call and no credential.
|
|
|
350
418
|
| `EVERFUR_MCP_HTTP_HOST` / `PORT` / `PATH` | Optional HTTP listener configuration; defaults to `127.0.0.1:3100/mcp`. `EVERFUR_MCP_HTTP_PORT` is also the hosted service's port. |
|
|
351
419
|
| `EVERFUR_MCP_HTTP_ALLOWED_HOSTS` | Required for any non-loopback bind; comma-separated public hostnames only. |
|
|
352
420
|
| `EVERFUR_MCP_HTTP_ALLOWED_ORIGINS` | Optional browser-origin allowlist. Origins are rejected unless explicitly listed. |
|
|
353
|
-
| `MCP_PUBLIC_URL` | Everfur-internal: the FULL endpoint URL of the hosted service (`everfur-mcp-hosted`), path included (`https://mcp.everfur.com/mcp`), exactly as a partner pastes it into Claude. It is the OAuth resource every token names and the base of every 401's metadata pointer; a bare origin is refused at start. With `EVERFUR_API_BASE_URL`, `EVERFUR_MCP_HTTP_PORT` and `MCP_TRUSTED_PROXY_HOPS` it is the hosted task's whole environment. Partners do not set this. |
|
|
421
|
+
| `MCP_PUBLIC_URL` | Everfur-internal: the FULL endpoint URL of the hosted service (`everfur-mcp-hosted`), path included (`https://mcp-staging.everfur.com/mcp` on the staging deployment), exactly as a partner pastes it into Claude. It is the OAuth resource every token names and the base of every 401's metadata pointer; a bare origin is refused at start. With `EVERFUR_API_BASE_URL`, `EVERFUR_MCP_HTTP_PORT` and `MCP_TRUSTED_PROXY_HOPS` it is the hosted task's whole environment. Partners do not set this. |
|
|
354
422
|
| `MCP_ALLOWED_HOSTS` | Everfur-internal, optional: extra `Host` values the hosted service accepts beside its own. `MCP_PORT` is read only when `EVERFUR_MCP_HTTP_PORT` is unset. Partners do not set these. |
|
|
355
|
-
| `MCP_ALLOWED_ORIGINS` | Everfur-internal, optional: extra `Origin` values the hosted service's MCP endpoint accepts beside `https://claude.ai` and `https://
|
|
423
|
+
| `MCP_ALLOWED_ORIGINS` | Everfur-internal, optional: extra `Origin` values the hosted service's MCP endpoint accepts beside `https://claude.ai`, `https://claude.com` and `https://chatgpt.com`; any other `Origin` is refused with `403`. A browser page at an accepted origin gets its CORS preflight answered and can read the `401` challenge. Partners do not set this. |
|
|
356
424
|
| `MCP_TRUSTED_PROXY_HOPS` | Everfur-internal, optional: how many proxies appended to `X-Forwarded-For` (`1` behind the load balancer). Keys the hosted service's per-client budget of unauthenticated failures; `0` (default) uses the socket address. Partners do not set this. |
|
|
425
|
+
| `OPENAI_APPS_CHALLENGE_TOKEN` | Everfur-internal, optional: the domain verification token OpenAI's plugin portal generates. Set, the hosted service serves it as the whole plain-text body of `/.well-known/openai-apps-challenge` on its own host; unset or blank, that path is a `404`. Never logged. Partners do not set this. |
|
|
357
426
|
|
|
358
427
|
**Getting keys:** Everfur keys are currently provisioned by the Everfur team during partner onboarding;
|
|
359
428
|
there is no self-serve signup yet. Contact [support@everfur.com](mailto:support@everfur.com) to get set
|
|
@@ -361,8 +430,14 @@ up. The publishable key is designed to ship inside your app; the secret key is n
|
|
|
361
430
|
|
|
362
431
|
## Documentation
|
|
363
432
|
|
|
364
|
-
The
|
|
365
|
-
[
|
|
433
|
+
The integration guide, API reference, error catalog and testing guide are at
|
|
434
|
+
[sdk.everfur.com/v1/docs](https://sdk.everfur.com/v1/docs/index.html): adoption paths, the HTTP contract, API
|
|
435
|
+
keys, the launch checklist and troubleshooting.
|
|
436
|
+
|
|
437
|
+
This page used to link to `github.com/Everfur-Health/everfur-sdk-rn`, which is a PRIVATE repository: the
|
|
438
|
+
link returned 404 for every partner who clicked it, since a partner is outside Everfur by definition. If
|
|
439
|
+
a doc you need is not on the site yet, ask [support@everfur.com](mailto:support@everfur.com) rather than
|
|
440
|
+
looking for a repository you cannot open.
|
|
366
441
|
|
|
367
442
|
## License
|
|
368
443
|
|