History

Version Packages (#1811)

Rhys Sullivan committed 2 months agov1.6.3

Commit 2ddfa291 parent 369fa0a99 files · +706 −487Browse files

Unified · Split

99 files
  1. .changeset/concurrent-stale-tools-sync.md +0 −11
  2. .changeset/defer-irreversible-cleanup.md +0 −15
  3. .changeset/dialog-outside-click-keeps-form-state.md +0 −11
  4. .changeset/expired-authorization-session-sweep.md +0 −11
  5. .changeset/foreign-org-slug-not-found.md +0 −13
  6. .changeset/graphql-introspection-credential-log.md +0 −24
  7. .changeset/health-response-sample-scrub.md +0 −16
  8. .changeset/legacy-bigint-storage-class.md +0 −11
  9. .changeset/mcp-add-url-typing-probe.md +0 −11
  10. .changeset/mcp-integration-families.md +0 −5
  11. .changeset/mcp-oauth-declared-scopes.md +0 −11
  12. .changeset/mcp-pool-idle-sweep.md +0 −13
  13. .changeset/mcp-pre-initialize-method-not-found.md +0 −9
  14. .changeset/mcp-remote-request-headers.md +0 −15
  15. .changeset/mcp-stdio-edit-ui.md +0 −26
  16. .changeset/mcp-stdio-env-isolation.md +0 −11
  17. .changeset/mcp-tool-meta-passthrough.md +0 −11
  18. .changeset/misconfigured-health-status.md +0 −7
  19. .changeset/oauth-refresh-cross-session.md +0 −13
  20. .changeset/oauth-refresh-store-writability-gate.md +0 −13
  21. .changeset/oauth-resource-explicit-absence.md +0 −17
  22. .changeset/oauth-token-endpoint-error-leak.md +0 −35
  23. .changeset/onepassword-multiple-vaults.md +0 −11
  24. .changeset/openapi-multipart-file-fields.md +0 −12
  25. .changeset/persist-mcp-install-options.md +0 −5
  26. .changeset/plugin-storage-bulk-upserts.md +0 −7
  27. .changeset/scope-mcp-stream-replay.md +0 −5
  28. .changeset/seat-based-team-pricing.md +0 −22
  29. .changeset/selfhost-additional-trusted-origins.md +0 −10
  30. .changeset/sidebar-integration-connect.md +0 −15
  31. .changeset/tools-read-stale-sync-grace.md +0 −11
  32. .changeset/update-check-suppress-false-nags.md +0 −14
  33. apps/cli/CHANGELOG.md +248 −0
  34. apps/cli/package.json +1 −1
  35. apps/cloud/CHANGELOG.md +41 −0
  36. apps/cloud/package.json +1 −1
  37. apps/desktop/CHANGELOG.md +2 −0
  38. apps/desktop/package.json +1 −1
  39. apps/host-selfhost/CHANGELOG.md +22 −0
  40. apps/host-selfhost/package.json +1 −1
  41. apps/local/CHANGELOG.md +34 −0
  42. apps/local/package.json +1 −1
  43. bun.lock +33 −33
  44. e2e/CHANGELOG.md +12 −0
  45. e2e/package.json +1 −1
  46. examples/all-plugins/CHANGELOG.md +14 −0
  47. examples/all-plugins/package.json +1 −1
  48. examples/docs-sdk-quickstart/CHANGELOG.md +8 −0
  49. examples/docs-sdk-quickstart/package.json +1 −1
  50. packages/core/analytics/CHANGELOG.md +7 −0
  51. packages/core/analytics/package.json +1 −1
  52. packages/core/api/CHANGELOG.md +9 −0
  53. packages/core/api/package.json +1 −1
  54. packages/core/cli/CHANGELOG.md +8 −0
  55. packages/core/cli/package.json +1 −1
  56. packages/core/config/CHANGELOG.md +7 −0
  57. packages/core/config/package.json +1 −1
  58. packages/core/execution/CHANGELOG.md +8 −0
  59. packages/core/execution/package.json +1 −1
  60. packages/core/fumadb/CHANGELOG.md +7 −0
  61. packages/core/fumadb/package.json +1 −1
  62. packages/core/sdk/CHANGELOG.md +19 −0
  63. packages/core/sdk/package.json +1 −1
  64. packages/core/vite-plugin/CHANGELOG.md +7 −0
  65. packages/core/vite-plugin/package.json +1 −1
  66. packages/hosts/cloudflare/CHANGELOG.md +10 −0
  67. packages/hosts/cloudflare/package.json +1 −1
  68. packages/hosts/mcp-apps-shell/CHANGELOG.md +8 −0
  69. packages/hosts/mcp-apps-shell/package.json +1 −1
  70. packages/kernel/core/CHANGELOG.md +2 −0
  71. packages/kernel/core/package.json +1 −1
  72. packages/kernel/runtime-quickjs/CHANGELOG.md +7 −0
  73. packages/kernel/runtime-quickjs/package.json +1 −1
  74. packages/kernel/runtime-workerd-subprocess/CHANGELOG.md +7 −0
  75. packages/kernel/runtime-workerd-subprocess/package.json +1 −1
  76. packages/plugins/desktop-settings/CHANGELOG.md +7 −0
  77. packages/plugins/desktop-settings/package.json +1 −1
  78. packages/plugins/encrypted-secrets/CHANGELOG.md +7 −0
  79. packages/plugins/encrypted-secrets/package.json +1 −1
  80. packages/plugins/example/CHANGELOG.md +7 −0
  81. packages/plugins/example/package.json +1 −1
  82. packages/plugins/file-secrets/CHANGELOG.md +7 −0
  83. packages/plugins/file-secrets/package.json +1 −1
  84. packages/plugins/graphql/CHANGELOG.md +10 −0
  85. packages/plugins/graphql/package.json +1 −1
  86. packages/plugins/keychain/CHANGELOG.md +7 −0
  87. packages/plugins/keychain/package.json +1 −1
  88. packages/plugins/mcp/CHANGELOG.md +36 −0
  89. packages/plugins/mcp/package.json +1 −1
  90. packages/plugins/onepassword/CHANGELOG.md +9 −0
  91. packages/plugins/onepassword/package.json +1 −1
  92. packages/plugins/openapi/CHANGELOG.md +18 −0
  93. packages/plugins/openapi/package.json +1 −1
  94. packages/plugins/provider-service-split/CHANGELOG.md +8 −0
  95. packages/plugins/provider-service-split/package.json +1 −1
  96. packages/plugins/toolkits/CHANGELOG.md +9 −0
  97. packages/plugins/toolkits/package.json +1 −1
  98. packages/react/CHANGELOG.md +28 −0
  99. packages/react/package.json +1 −1
.changeset/concurrent-stale-tools-sync.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**Stale tool catalogs refresh together instead of one after another, and self-host can set the freshness window**
6
7A tools read rebuilds every connection whose catalog has gone stale. Those rebuilds each dial their own upstream, but ran strictly one after another, so a host with several stale remote catalogs paid the sum of every server's latency on the read that tripped the TTL. The upstream listings now run concurrently, bounded so a large stale set cannot open an unbounded number of listings from one read.
8
9Only the listings overlap. Each rebuild's catalog write stays single-file, because a self-host database is one connection issuing raw `BEGIN`/`COMMIT` and a second transaction opened while one is live fails outright. A rebuild that fails now also logs a warning naming the connection and the reason, instead of disappearing: the read still succeeds on the stale-but-working catalog and the other connections still finish, but a permanently broken connection no longer re-fails silently on every read.
10
11Self-host also exposes the freshness window as `EXECUTOR_TOOLS_SYNC_TTL_MS`. Leave it unset for the 15-minute default, or set `off` (equivalently `null` or `false`, in any case) to disable time-based re-sync and leave stale-marking and config revision as the only refresh triggers. The value forwards to the SDK verbatim, so `0` keeps its SDK meaning: every catalog is expired on every read. A malformed, negative, or too-large-to-represent value is refused at boot rather than silently falling back to the default.
.changeset/defer-irreversible-cleanup.md+0−15
@@ -1,15 +0,0 @@
1---
2"executor": patch
3---
4
5**Irreversible cleanup now waits for the transaction to commit, and plugins can do the same**
6
7`oauth.removeClient` deleted the client row and then deleted the client secret from the credential provider. The provider does not enlist in the caller's transaction and does not roll back with it, so an abort restored the client row while its secret stayed destroyed — a client that looks configured and can never authenticate again. The deletion now waits until the removal is durable and is discarded if the removal rolls back. With no transaction active it runs immediately, exactly as before.
8
9Deferring the deletion is not enough on its own. The secret is stored under a key derived from the app's `(owner, slug)` identity alone, so the key outlives the row it belonged to: whoever holds that identity when the deletion finally runs owns the key. A slug registered again before the removal committed would lose the new app's secret to the old app's queued deletion — the same unauthenticatable client, reached the other way round. The deferred deletion now re-checks that the app is still gone and stands down when it is not. A removal that matched no row also no longer queues a deletion at all: it removed nothing, so it has no claim on the key, which may well hold another subject's live secret.
10
11The same trap was reachable by plugins and they had no way out of it. `removeConnection` and `removeIntegration` run inside core's removal transaction — deliberately, so a plugin's own rows die atomically with the connection — which makes them exactly the wrong place to revoke a token at the provider's API, delete a remote object, or notify a third party. Nothing in the hooks' documentation said so, and `PluginCtx` exposed `transaction` but nothing to defer past it.
12
13`PluginCtx` gains `afterCommit`. It runs the effect once the outermost transaction commits, discards it if that transaction rolls back, and runs it immediately when no transaction is active. The lifecycle hooks now document that they run inside core's transaction and that outside-world work belongs in `afterCommit`.
14
15Sequencing work after your own `transaction(...)` call is not equivalent, and the documentation says so explicitly: `transaction` nests by pass-through, so inside an active transaction the inner call simply runs its effect and "afterwards" is still before any commit.
.changeset/dialog-outside-click-keeps-form-state.md+0−11
@@ -1,11 +0,0 @@
1---
2"@executor-js/react": patch
3---
4
5**A click outside a dialog or sheet no longer discards the form inside it**
6
7Radix dismisses an overlay surface on any un-prevented outside interaction, and `DialogContent` and `SheetContent` only prevented that for clicks landing in a portaled combobox or select popup. Every other outside click fell through to dismissal, so a stray click on the page behind a form — after switching windows to copy an ID, for example — closed the surface and destroyed what the user had typed. These surfaces unmount their state on close by design, so nothing was recoverable.
8
9The default is now the opposite: an outside interaction keeps the surface open. Escape and the close button are unchanged and still close it. `DialogContent` and `SheetContent` take a new `dismissOnOutsideClick` prop for surfaces with nothing to lose — confirmations, pickers, and read-only panels — and the portaled-popup guard still applies there, so choosing a combobox option never dismisses.
10
11`CommandDialog` sets `dismissOnOutsideClick` on by default, because a command palette holds only a search string and clicking away is the expected way to leave it.
.changeset/expired-authorization-session-sweep.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**Abandoned authorization sessions no longer keep their PKCE verifier forever**
6
7An OAuth authorization session stores its PKCE verifier so the callback can redeem the code. `complete` discarded an expired session lazily, but an _abandoned_ flow is never completed, so that check never ran for it and nothing else swept the table — the verifier sat there in plaintext indefinitely.
8
9Starting a new authorization now sweeps sessions that have already expired. Doing it on `start` bounds the table by how often authorization is begun rather than by how often it is abandoned, and needs no scheduler in any host. A session whose completion cannot be retried is dropped rather than left behind.
10
11The sweep only ever reaches rows the caller can already see, so one member's authorization never touches another member's sessions. It is best-effort: a sweep that fails logs a warning and lets the authorization continue.
.changeset/foreign-org-slug-not-found.md+0−13
@@ -1,13 +0,0 @@
1---
2"executor": patch
3---
4
5**A console URL naming an organization you cannot see is a not-found page, every time**
6
7Opening `/<some-other-slug>/policies` sometimes rendered the full authenticated console — sidebar, org switcher showing your OWN organization, page chrome — under an address naming an organization you are not a member of. The page body was a failing org-scoped query with a Retry button, so the workspace on screen belonged to nobody and the URL belonged to someone else.
8
9The shell's not-found only fired once `/account/me` had answered for the URL's slug. Until then the console read its identity from the auth-hint cookie, which always names the organization the session last landed in, never the one in the address bar. So the first paint answered a question about a different organization and built a whole workspace out of it, and whether you ever saw that depended on how fast the server replied.
10
11The shell is now built only from an answer that names the organization the URL names. A slug the current answer does not cover renders nothing at all until `/account/me` resolves for that slug, and then either the workspace or — for an organization this session cannot see — the not-found page. The URL is never rewritten: a wrong address stays a wrong address.
12
13The ordinary cold load is untouched. The hint names the slug already in the URL, so it matches on the very first paint and the shell renders with no round trip. Only a slug the hint does not name waits: a foreign one, and the single frame after switching organizations, which now paints the organization the URL asked for instead of briefly showing the previous one.
.changeset/graphql-introspection-credential-log.md+0−24
@@ -1,24 +0,0 @@
1---
2"executor": patch
3---
4
5**GraphQL introspection no longer logs a credential carried in the endpoint URL**
6
7`query` is a supported credential carrier, so a GraphQL endpoint can be reached with `?token=<secret>`. Introspection built its request from a URL **string**, and `HttpClientRequest.setUrl` keeps a string verbatim as `request.url`. Every `HttpClientError` renders `${method} ${request.url}` into its `message` getter, and introspection logs the raw failure cause — so on any transport failure or non-JSON response, the connection's secret was written to the process log.
8
9The request is now built from a URL **object**, which moves the query into `request.urlParams` and clears it from `request.url`. The secret is therefore absent from the error message, and from anything else that renders the request URL. The credential still reaches the upstream: the client recombines url and urlParams when it executes the request. The endpoint's own query string is handled the same way, not just the separately-supplied query parameters, since a configured endpoint can carry a credential too.
10
11**The query string is now normalized on the wire.** Recombination appends each pair through `URLSearchParams`, so the query is re-serialized in form-urlencoded form instead of passed through byte-for-byte:
12
13- a space written as `%20` is sent as `+`
14- `~` and `!'()` are percent-encoded
15- a valueless `?flag` is sent as `flag=`
16
17Key order, repeated keys, and already-encoded reserved characters are unchanged, and every parameter still decodes to the same value. This is not avoidable while the fix holds: raw query bytes only survive inside `request.url`, which is the one field every error message renders, so byte-transparency and keeping the credential out of the log cannot both hold. An upstream that signs its raw query string is the case to watch. The exact resulting URLs are pinned by test.
18
19Two endpoints are now rejected up front with an `invalid-endpoint` failure rather than dialed:
20
21- an endpoint that is not a valid URL, which cannot be split this way and would otherwise be sent without the query parameters it was asked to include
22- an endpoint carrying userinfo (`https://user:pass@host/…`), which `URL` keeps in the origin, so it would stay in `request.url` and leak into error messages exactly the way a query-carried secret used to
23
24Neither rejection echoes any part of the endpoint. A health check on such an integration now reports the invalid configuration and points the operator at the endpoint URL, instead of blaming the credential that was never sent.
.changeset/health-response-sample-scrub.md+0−16
@@ -1,16 +0,0 @@
1---
2"executor": patch
3---
4
5**Credentials are kept out of the health-check result that gets persisted**
6
7A health check stores a sample of the probed operation's response body, plus the extracted identity, in `connection.last_health` — so whatever those carry is written to the database. The operation is user-chosen from the plugin's catalog, which means it can just as easily be a key-listing endpoint as a `/me`, and those return secrets that no scrub of the connection's own credential value can recognise, because they are different secrets entirely.
8
9Two passes now cover both kinds of secret:
10
11- **By key name.** Leaves whose key names a credential (`token`, `api_key`, `secret`, `authorization`, `session`, …) have their value replaced with `[redacted]`. The row itself is kept, so the live preview still shows the response shape and the identity picker still works. Keys that merely contain a matching substring, such as `author`, are left alone. camelCase spellings are recognised too: `accessToken`, `refreshToken`, `clientSecret`, `privateKey` and `sessionId` have no separator before the credential word, so a matcher that only looks for one reads them as innocent.
12- **By value.** The OpenAPI health check removes the connection's own credential value from each sampled value, covering the other direction: a body that echoes back the key it was authenticated with under an innocent-looking name. This runs before the sample's 120-char truncation, not after — truncating first leaves a prefix of a long credential that an exact-value scrub can no longer match, and that prefix is what would be persisted.
13
14The key check reads a dotted path two ways. It uses the nearest NAMED segment, because array elements are named by index: `{"tokens": ["sk-live-…"]}` produces the path `tokens.0`, and testing the literal `"0"` matches nothing. It also uses an enclosing array container, because a key listing returns `{"api_keys": [{"value": "sk-live-…"}]}`, whose path is `api_keys.0.value` — the nearest named segment there is the innocent `value`, and only the array's own key says what the collection holds. A collection whose key names nothing, such as `names.0`, is still shown in full.
15
16The extracted `identity` goes through both passes as well. It is read straight off the raw body, so it previously bypassed them even though it is persisted the same way, and `identityField` is user-chosen from whatever the picker listed.
.changeset/legacy-bigint-storage-class.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**Saved integrations come back after an upgrade left an OAuth expiry in the old number format**
6
7Some installs lost every saved integration from the MCP gateway at once. The credentials were never deleted — the gateway simply could not read the table they live in, so it served an empty tool list and restarting did not help.
8
9The `connection.expires_at` column records when an OAuth access token expires. It used to be a plain number; it now holds the value's digits, because a millisecond timestamp is larger than a 32-bit integer. SQLite does not rewrite rows when a column's type changes, so a connection saved by an older build still held the old form. Reading one back failed, and because the failure happened while mapping the row, it failed the whole query rather than that one field — one stale row was enough to hide every integration.
10
11A boot-time migration now converts those values to the current form. It runs before anything reads the table, so the integrations are back on the first restart after upgrading. It only touches values still in the old numeric form: rows already written by a current build are left exactly as they are, and it runs once.
.changeset/mcp-add-url-typing-probe.md+0−11
@@ -1,11 +0,0 @@
1---
2"@executor-js/plugin-mcp": patch
3---
4
5**The add-MCP form stops dialling the server URL while it is still being typed**
6
7The Server URL field auto-probes the endpoint after a 400ms pause. The only condition on that probe was that the trimmed value was non-empty, so every pause in typing dialled whatever was in the field: "h", "http://", the "a" in "http://a". Each of those probes failed, and the field dropped into a loading state and then an error with a retry button, for a value the user never meant to submit.
8
9The probe now runs only when the value looks like a finished endpoint: it parses as a URL, its scheme is http or https, and its hostname is either a local development host or has a dot with a label on each side. The debounce is unchanged, so a completed URL is still probed without the user having to submit.
10
11A probe that is superseded is also no longer allowed to answer. The field could previously report the outcome of a request for a URL that had since been edited, because each probe dispatched its result unconditionally. Editing the URL now invalidates any probe already in flight, and its reply is discarded rather than applied to the current value.
.changeset/mcp-integration-families.md+0−5
@@ -1,5 +0,0 @@
1---
2"@executor-js/plugin-mcp": patch
3---
4
5Allow MCP integrations to declare a catalog family and group any family with multiple services in the integrations UI.
.changeset/mcp-oauth-declared-scopes.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**Fix: allow MCP integrations to declare OAuth scopes when resource metadata omits them**
6
7MCP OAuth methods can now carry an optional non-empty scope list. Declared scopes
8take precedence over protected-resource scope discovery, so servers with fixed
9scopes can connect even when their dynamically registered OAuth client has no
10resource identifier. Existing integrations without declared scopes keep
11discovering them from the server at connect time.
.changeset/mcp-pool-idle-sweep.md+0−13
@@ -1,13 +0,0 @@
1---
2"executor": patch
3---
4
5**Idle MCP connections age out on the pool's next acquire, even when their identity is never dialled again**
6
7The pool's five-minute idle window was only consulted against the entry being requested, so an identity that was never asked for a second time was never examined a second time. Its session stayed open and authenticated for as long as the pool lived, holding the bearer token or API key it was dialled with. The advertised bound applied only to connections that happened to be reused.
8
9`acquire` now sweeps every entry past the window, closing each one, rather than just the entry matching the key. This stays lazy in the sense the pool intends — activity drives it, there is no timer and no background fiber — and the map holds at most one entry per identity, so the scan is trivial.
10
11Because the sweep is paid for by whichever invocation acquires next, it cannot be allowed to stall that caller. The expired entries leave the pool synchronously, before any close is awaited, and the closes then run concurrently with each one bounded by a two-second timeout — so a server that accepts a close and goes quiet is abandoned rather than waited on, and cannot hold up an unrelated request or the connections queued behind it.
12
13Reuse is unchanged: an entry still inside the window is left alone, and a second call for the same identity still gets the parked session rather than a fresh dial.
.changeset/mcp-pre-initialize-method-not-found.md+0−9
@@ -1,9 +0,0 @@
1---
2"@executor-js/local": patch
3---
4
5**An unsupported method probed before `initialize` no longer kills the MCP connection**
6
7Only `initialize` can open a session, so the streamable-HTTP transport answered every other pre-session method with HTTP 400 + `-32000 Server not initialized`. A 400 is a transport-level failure, so clients dropped the connection instead of treating it as one request failing — a client that opens with an optional probe (MCP 2026-07-28 clients lead with `server/discover`) was disconnected before it could fall back to `initialize`. Over `executor mcp`, which bridges this endpoint to stdio, that closed the client's pipe outright.
8
9Pre-session dispatch now answers any method other than `initialize` with `-32601 Method not found` on a normal 200, which is a per-request error, so the connection survives and the handshake proceeds. This replaces only that one answer: a POST with a bad `Accept` or `Content-Type` still gets the transport's 406 or 415, and a message that is not a valid JSON-RPC request still gets its parse error.
.changeset/mcp-remote-request-headers.md+0−15
@@ -1,15 +0,0 @@
1---
2"executor": patch
3---
4
5**Fix: add remote MCP servers that sit behind an authenticating proxy**
6
7The add-MCP form now carries an optional request headers editor. The name/value
8pairs are sent on the connection check and on every later request, so an
9endpoint gated by an edge authenticator — a Cloudflare Access service token,
10for example — can be discovered and added.
11
12A `403` from such a gate is also no longer read as an unreachable server. It is
13classified the same way a `401` is: the endpoint needs credentials, so the add
14flow continues to the auth step instead of stopping on "Couldn't reach this
15URL".
.changeset/mcp-stdio-edit-ui.md+0−26
@@ -1,26 +0,0 @@
1---
2"executor": patch
3---
4
5**Stdio MCP integrations can be edited from the UI**
6
7The integration Edit sheet showed stdio servers as read-only text and told you
8to remove and recreate the integration to change its command. Fixing a typo in
9an argument, moving a server to a new path, or adding a static environment
10variable meant editing `executor.jsonc` by hand, or losing the integration's
11connections and tool policies to a delete-and-re-add.
12
13The sheet now edits the command, its arguments, the working directory, and the
14declared environment map, staged and applied by the sheet's own Save like the
15remote editor beside it. Arguments use the same quote-aware parsing as the add
16flow, so an argument containing spaces survives a round trip.
17
18The environment field edits the DECLARED static variables only. A stdio server
19receives those plus a small fixed base set — it does not inherit executor's
20environment — and secret values still belong to the connection, entered per
21account against the server's declared `stdio_env` method.
22
23Saving revises the integration config, which is already enough to rebuild the
24tool catalog: connections whose catalog predates the revision re-list on their
25next read, so an edited command's tools are correct without an explicit
26refresh.
.changeset/mcp-stdio-env-isolation.md+0−11
@@ -1,11 +0,0 @@
1---
2"@executor-js/plugin-mcp": patch
3---
4
5**Stdio MCP servers no longer inherit executor's full environment**
6
7A stdio MCP server that declared any `env` at all was spawned with every environment variable this process holds. The MCP SDK already guards against that: it spawns with `{ ...getDefaultEnvironment(), ...serverParams.env }`, where `getDefaultEnvironment()` is a sudo-style safe-list of `HOME`, `LOGNAME`, `PATH`, `SHELL`, `TERM` and `USER`. Passing `{ ...process.env, ...config.env }` did not add to that safe-list, it overwrote it. In practice, adding one third-party `npx` server went from "this server can see the API key I gave it" to "this server also holds `EXECUTOR_SECRET_KEY`, the key that decrypts every other stored credential, plus `EXECUTOR_AUTH_TOKEN` and `DATABASE_URL`". The leak sat on the `config.env` branch — the branch a credential-bearing integration takes.
8
9A stdio server now receives the SDK's safe-list, the variables declared on the source config, and one short allowlist of infrastructure variables read from the host: `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY` (both spellings), `NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE` and `SSL_CERT_DIR`. Those carry no credential, no source config declares them, and a server behind a corporate proxy or an intercepting CA cannot reach anything without them — the same reasoning and the same list `service install` already uses when it bakes a supervised unit's minimal environment. The declared `env` wins on a key collision. On Windows that collision is resolved case-insensitively, because the OS treats `Path` and `PATH` as one variable while a JavaScript spread does not: a declared `http_proxy` now replaces an inherited `HTTP_PROXY` instead of travelling beside it, which would have left the child reading whichever spelling Windows resolved first.
10
11If a stdio server relied on some other variable arriving from the host, set it explicitly on the source's `env`. That is now the only way anything beyond the lists above reaches a server, and it is the mechanism that already existed for it.
.changeset/mcp-tool-meta-passthrough.md+0−11
@@ -1,11 +0,0 @@
1---
2"@executor-js/plugin-mcp": patch
3---
4
5**An MCP tool's reserved `_meta` map survives `tools/list` decoding and reaches the persisted catalog**
6
7The MCP spec reserves `_meta` on `Tool` for implementation-defined data, and servers use it for host-only routing and policy hints that do not belong in the closed `annotations` set. The plugin decoded each listed tool with a closed struct that did not declare the field, so `_meta` was discarded before the manifest entry was built. A host that embeds the plugin as its MCP client had no way to recover it: no hook exposes the raw `tools/list` result, and `connections.refresh()` answers with already-built tools.
8
9The listed-tool decode now declares `_meta`, and the manifest entry carries it through. Executor's own `Tool` has no `_meta` field, so `toToolDef` stamps the map into the `mcp` envelope the plugin already persists in each tool row's annotations, next to the real MCP tool name. The stamp schema declares it too, so it is not stripped a second time when a row is read back at invoke time. A host reads it from `annotations.mcp._meta`.
10
11The map stays opaque. Nothing in the plugin interprets its contents, and it is never merged into anything the model sees. Because it is entirely server-controlled, it is decoded permissively: a `_meta` that is not the spec's map shape is ignored for that tool rather than failing the whole-list decode, which would otherwise drop every tool the server advertises.
.changeset/misconfigured-health-status.md+0−7
@@ -1,7 +0,0 @@
1---
2"executor": patch
3---
4
5**A disabled upstream API now reports `misconfigured` instead of `expired`**
6
7A 403 caused by the provider disabling the API (Google SERVICE_DISABLED / accessNotConfigured shapes) is a configuration problem, not a credential problem — reconnecting cannot fix it. Health checks now classify it as a fifth status, `misconfigured`, shown with an amber badge and a link to the provider console instead of a Reconnect prompt. Ordinary 401/403 credential rejections still report `expired`.
.changeset/oauth-refresh-cross-session.md+0−13
@@ -1,13 +0,0 @@
1---
2"@executor-js/sdk": patch
3---
4
5Share the OAuth refresh gate across execution stacks so a rotating refresh token is redeemed once.
6
7The in-flight refresh gate was built inside `createExecutor`, so it only covered one execution stack. A host builds a fresh stack per MCP session, and now per request, so two sessions resolving the same connection each read the same stored refresh token and each believed they were the refresh winner. Against a provider that rotates refresh tokens, the loser redeems a token the winner already spent, and a provider that detects reuse revokes the whole token family: the connection dies and the user has to reauthorize. The first refresh always succeeds, so the fault stayed invisible until a later expiry.
8
9The gate now hangs off the root database handle, which is the object hosts already share across sessions and requests, so every stack over one handle converges on one gate. Its key includes the tenant, because a gate that spans tenants would otherwise let two tenants collide on one entry.
10
11The grant also runs on its own detached fiber that callers await, rather than on whichever caller registered it. Sharing an entry across stacks would otherwise share the first caller's cancellation: a disconnected MCP client or an execution deadline would fail every peer waiting on that entry, and would abandon a refresh token the authorization server had already rotated, which is itself a dead connection. A cancelled peer now detaches without touching the grant, and a grant nobody is left waiting on still settles and still persists the rotated token.
12
13Deduplication covers one database handle in one process. A host that builds a fresh handle per request or per session, and any multi-instance or multi-replica deployment, is out of scope here and still needs database-backed coordination, such as a compare-and-swap on the stored refresh token.
.changeset/oauth-refresh-store-writability-gate.md+0−13
@@ -1,13 +0,0 @@
1---
2"executor": patch
3---
4
5**A credential-store outage no longer costs an OAuth connection its grant**
6
7Refreshing an OAuth token spends the stored refresh token: the authorization server rotates it, so the copy we sent stops working the moment the grant succeeds and the rotated one is the only thing that can mint again. Persisting the rotated token first bounds what a partial write can lose, but it cannot help when the store is refusing writes outright — the grant has already run, there is nowhere to put the successor, and every later refresh replays a token the server has revoked. The connection then reports `invalid_grant` and demands a re-auth over what was only a storage blip.
8
9The refresh is now gated on a store that is proven writable. Before the grant runs, it writes a fixed value to an item of its own that holds no credential and sits in the same partition as the connection's tokens. A store that cannot take that write fails the resolve while the stored refresh token is still valid, so the connection recovers on its own once the store does.
10
11The probe deliberately does not test the store by rewriting the refresh token with the value it just read. That is a read-then-write with no compare-and-set, and two instances refreshing one connection would lose the newer token to it: one reads the stored token, the other spends that same token and stores its rotated replacement, and the first then writes the spent one back over the replacement. The connection would die exactly the way the gate is meant to prevent.
12
13The probe also removes a write rather than adding one in the common case. Authorization servers that do not rotate hand back the same refresh token, and that value is no longer re-persisted when it has not changed — a rotated token never matches, so the write that matters still happens.
.changeset/oauth-resource-explicit-absence.md+0−17
@@ -1,17 +0,0 @@
1---
2"executor": patch
3"@executor-js/react": patch
4---
5
6**An OAuth app can now be registered without an RFC 8707 resource, and that absence holds on every request**
7
8Microsoft Entra v2 rejects any authorization request that carries both a v2 `scope` (such as `https://api.fabric.microsoft.com/.default`) and the RFC 8707 `resource` parameter, failing with `AADSTS9010010` before the consent screen. Executor made that unavoidable for MCP servers behind Entra: registering an app for an MCP integration always derived the MCP endpoint as the resource, the form had no field to change it, and so every request carried the parameter Entra rejects.
9
10The register/edit OAuth app form now shows the resource indicator. It is still prefilled for MCP servers — nothing changes for providers that accept the parameter — but it can be cleared, and a cleared value persists as "no resource". A resource-less app then omits `resource` on all four grants alike: the authorization request, the code exchange, token refresh, and client-credentials. Symmetry matters here — sending `resource` on authorize but not on the token request (or the reverse) would bind the two tokens to different audiences.
11
12Two adjacent gaps closed with it:
13
14- MCP scope discovery no longer depends on the app's resource. It now falls back to the integration's own discovery URL (the MCP endpoint), so clearing the resource does not break connecting.
15- Token refresh for a first-party OAuth app dropped the app's configured resource, refreshing to a different audience than the original grant. It now sends the same resource the authorization request sent.
16
17Apps that keep their resource — the default for every discovered MCP server — behave exactly as before: the parameter is sent on every grant, as the MCP authorization spec expects.
.changeset/oauth-token-endpoint-error-leak.md+0−35
@@ -1,35 +0,0 @@
1---
2"executor": patch
3---
4
5**Keep token material out of OAuth token-endpoint error messages**
6
7A token-endpoint failure renders a preview of the upstream body into its
8message, and that message is persisted onto connection health, returned to the
9caller, and carried into telemetry. On a malformed HTTP 200 the body being
10previewed is a _successful_ token response, so an access token and a refresh
11token could be rendered into it.
12
13The preview is now built from an allowlist of fields that are safe to show
14(`error`, `errors`, `error_description`, `error_uri`, plus `code`, `message`,
15and `detail` nested inside them) instead of a denylist of fields to hide. A
16field nobody anticipated is omitted by default rather than printed by default.
17Keys stay visible and only non-allowlisted string values are replaced, so an
18operator can still read the shape of what the server sent. `code` is readable
19only when nested, because at the top level of a token response it is the RFC
206749 authorization code.
21
22Form-encoded bodies take the same allowlist, the walk over a body is
23depth-bounded, and the failure summary records the token endpoint's hostname
24rather than its full URL, which can carry identifiers in its path.
25
26On that same malformed-200 path the failure no longer keeps the underlying
27rejection as its `cause`. That rejection carries the parsed token response, so
28keeping it put the raw tokens back into anything that renders the whole failure
29rather than only its message. Everything the path needs from the body — the
30status, the error code, the redacted preview — is read before the failure is
31built. A transport failure still keeps its cause, which is what tells a DNS miss
32apart from a refused connection.
33
34No public API changes. The dead-grant classification added for HTTP 200 refresh
35refusals is unaffected: it reads the HTTP status, not the rendered preview.
.changeset/onepassword-multiple-vaults.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**The 1Password provider can now be scoped to several vaults, with explicit per-vault addressing**
6
7The provider previously bound exactly one vault. The configuration now holds a set of vaults selected with checkboxes, and every reference is explicit about which vault it means: the item picker is a searchable list that shows each item's vault and stores a vault-qualified `op://` reference, so identically-titled items in different vaults can never collide. A bare item name is accepted only when it matches exactly one item across the selected vaults — a name that exists in more than one place fails with an error naming the matching vaults instead of silently picking one.
8
9Reopening the vault or item pickers no longer flashes a loading state: listings are retained and re-validated in the background, so the last-known list renders instantly.
10
11Configurations saved before this change keep working: the stored single-vault shape is read as a one-vault list and upgrades to the new shape the next time it is saved. The `status` tool reports `vaultNames` for all configured vaults and flags any configured vault the account can no longer see. Provider entries also gained an optional `group` label, which pickers use to show where an item lives.
.changeset/openapi-multipart-file-fields.md+0−12
@@ -1,12 +0,0 @@
1---
2"@executor-js/plugin-openapi": patch
3---
4
5Multipart file fields in an OpenAPI spec now accept and send real files. A `multipart/form-data` property typed as a binary or byte string is rewritten into the SDK's tool-file schema when the tool is extracted, so an agent supplies a file the same way it does everywhere else. On invocation those values are decoded back into `File`/`Blob` parts — as bare properties and inside arrays, with a per-property `encoding.contentType` applied to each file part — instead of being JSON-stringified into the form body, which is what upstreams were previously rejecting. A file whose base64 payload does not decode now fails the invocation and names the field, rather than sending the file envelope as JSON.
6
7The rewrite advertises only the shapes the request encoder can deliver. Two are deliberately left alone:
8
9- A binary field nested inside an object property. Only top-level multipart properties and direct items of a top-level array property become form parts.
10- A multipart body schema, or one of its properties, behind a `$ref`. Component schemas are carried through unresolved by design — the streaming compile path never materializes `components.schemas` — so a `$ref`'d file field keeps its declared binary string type.
11
12The rewrite reads the request schema's own `properties` map rather than walking every object key, so a `default`, `example`, or vendor extension that happens to look like a binary string schema is untouched. Descriptions, titles, and nullability on the replaced field are carried onto the file schema.
.changeset/persist-mcp-install-options.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": patch
3---
4
5Persist the Connect-an-agent card's transport, artifact, integration-search, and approval preferences in the browser so its generated MCP install command remains stable across page reloads.
.changeset/plugin-storage-bulk-upserts.md+0−7
@@ -1,7 +0,0 @@
1---
2"@executor-js/fumadb": patch
3"@executor-js/sdk": patch
4---
5
6Add a FumaDB bulk upsert query path and route plugin-storage bulk writes through
7it so existing rows are updated without delete/reinsert churn.
.changeset/scope-mcp-stream-replay.md+0−5
@@ -1,5 +0,0 @@
1---
2"executor": patch
3---
4
5Keep Last-Event-ID recovery scoped to its originating MCP stream.
.changeset/seat-based-team-pricing.md+0−22
@@ -1,22 +0,0 @@
1---
2"@executor-js/cloud": patch
3---
4
5**Team pricing is per member with unlimited executions**
6
7The Team plan moves from $150 per organization with a 250,000-execution
8allowance to $15 per member per month with unlimited executions. The
9`members` feature is unarchived in `autumn.config.ts` and billed in arrears
10on the seat count the app reports; Free keeps its 3-member, 100,000-execution
11shape and Enterprise stays custom with seat usage tracked for visibility.
12
13Seat counts reconcile from a full WorkOS recount (active members only —
14pending invites hold a seat for the plan gate but are not billed) after
15member removal, invitation acceptance, organization creation, and on every
16login callback, which also picks up joins the app never sees a mutation for
17(SSO JIT provisioning, join by domain, dashboard edits). Plans that predate
18seat pricing have no members balance and are skipped, so existing
19subscriptions keep billing exactly as before on their current plan version.
20
21The plans page, billing page, and marketing pricing cards now show the
22per-member price.
.changeset/selfhost-additional-trusted-origins.md+0−10
@@ -1,10 +0,0 @@
1---
2"executor": patch
3---
4
5Self-hosted instances can now allow additional browser origins without changing
6their canonical public URL. Set `EXECUTOR_TRUSTED_ORIGINS` to a comma-separated
7list of exact HTTP or HTTPS origins when one instance is intentionally reachable
8through multiple hostnames or addresses. OAuth callbacks, MCP metadata, approval
9links, and other generated URLs remain pinned to `EXECUTOR_WEB_BASE_URL`, and
10origins are never inferred from request headers.
.changeset/sidebar-integration-connect.md+0−15
@@ -1,15 +0,0 @@
1---
2"executor": patch
3---
4
5**Connect an integration from the sidebar**
6
7The sidebar lists your integrations on every console route, but connecting
8another one meant navigating back to the integrations page to reach its Connect
9action — the picker state was owned by that page, so the shared shell could
10render the list without being able to open the flow behind it.
11
12The connect dialog now belongs to the shell. A labelled plus button sits beside
13the sidebar's Integrations heading and opens the same picker, records the same
14event, and leaves the current route in place behind it. On mobile the navigation
15drawer closes first so the dialog gets the full viewport.
.changeset/tools-read-stale-sync-grace.md+0−11
@@ -1,11 +0,0 @@
1---
2"executor": patch
3---
4
5**Tools reads stop waiting on slow upstream servers**
6
7A tools read rebuilds every connection whose catalog has gone stale before answering. The rebuilds already ran concurrently, but the read still waited for all of them, so one slow or unreachable MCP server gated every catalog read behind its network timeout — a tools listing could take tens of seconds while healthy connections sat ready.
8
9A read now waits at most a short grace budget (2 seconds by default) for the rebuilds, then answers from the persisted catalog. The rebuilds keep running after the read returns and land on a later read, so the catalog still converges — it just no longer holds the reader hostage while it does. Overlapping reads share one in-flight rebuild per connection instead of stacking new ones.
10
11The budget is `toolsSyncGraceMs` on the SDK config. Pass `null` to restore the strict behavior, where a read blocks until every rebuild finishes and always reflects a fully converged catalog.
.changeset/update-check-suppress-false-nags.md+0−14
@@ -1,14 +0,0 @@
1---
2"executor": patch
3---
4
5**Fix: stop the update check from claiming a newer version is available on builds it cannot compare**
6
7A build stamped with the placeholder 0.0.0 version always compared as older
8than the latest release, and a prerelease on a channel with no matching
9dist-tag (rc, alpha, and similar) always lost the comparison too. Both cases
10now short-circuit to "no update available" before the check reaches the
11registry.
12
13This applies wherever the update check runs, so the CLI check and the sidebar
14update card both stop showing an update prompt that a user could never act on.
apps/cli/CHANGELOG.md+248−0
@@ -1,5 +1,253 @@
1# executor1# executor
2 2
3## 1.6.3
4
5### Patch Changes
6
7- [#1560](https://github.com/UsefulSoftwareCo/executor/pull/1560) [`8c20c33`](https://github.com/UsefulSoftwareCo/executor/commit/8c20c33817ad815b252c3d72290004905aedab10) Thanks [@Adityakk9031](https://github.com/Adityakk9031)! - **Stale tool catalogs refresh together instead of one after another, and self-host can set the freshness window**
8
9 A tools read rebuilds every connection whose catalog has gone stale. Those rebuilds each dial their own upstream, but ran strictly one after another, so a host with several stale remote catalogs paid the sum of every server's latency on the read that tripped the TTL. The upstream listings now run concurrently, bounded so a large stale set cannot open an unbounded number of listings from one read.
10
11 Only the listings overlap. Each rebuild's catalog write stays single-file, because a self-host database is one connection issuing raw `BEGIN`/`COMMIT` and a second transaction opened while one is live fails outright. A rebuild that fails now also logs a warning naming the connection and the reason, instead of disappearing: the read still succeeds on the stale-but-working catalog and the other connections still finish, but a permanently broken connection no longer re-fails silently on every read.
12
13 Self-host also exposes the freshness window as `EXECUTOR_TOOLS_SYNC_TTL_MS`. Leave it unset for the 15-minute default, or set `off` (equivalently `null` or `false`, in any case) to disable time-based re-sync and leave stale-marking and config revision as the only refresh triggers. The value forwards to the SDK verbatim, so `0` keeps its SDK meaning: every catalog is expired on every read. A malformed, negative, or too-large-to-represent value is refused at boot rather than silently falling back to the default.
14
15- [#1572](https://github.com/UsefulSoftwareCo/executor/pull/1572) [`27cb466`](https://github.com/UsefulSoftwareCo/executor/commit/27cb4664282308e86fdb43218b42fe457d22e782) Thanks [@GeiserX](https://github.com/GeiserX)! - **Irreversible cleanup now waits for the transaction to commit, and plugins can do the same**
16
17 `oauth.removeClient` deleted the client row and then deleted the client secret from the credential provider. The provider does not enlist in the caller's transaction and does not roll back with it, so an abort restored the client row while its secret stayed destroyed — a client that looks configured and can never authenticate again. The deletion now waits until the removal is durable and is discarded if the removal rolls back. With no transaction active it runs immediately, exactly as before.
18
19 Deferring the deletion is not enough on its own. The secret is stored under a key derived from the app's `(owner, slug)` identity alone, so the key outlives the row it belonged to: whoever holds that identity when the deletion finally runs owns the key. A slug registered again before the removal committed would lose the new app's secret to the old app's queued deletion — the same unauthenticatable client, reached the other way round. The deferred deletion now re-checks that the app is still gone and stands down when it is not. A removal that matched no row also no longer queues a deletion at all: it removed nothing, so it has no claim on the key, which may well hold another subject's live secret.
20
21 The same trap was reachable by plugins and they had no way out of it. `removeConnection` and `removeIntegration` run inside core's removal transaction — deliberately, so a plugin's own rows die atomically with the connection — which makes them exactly the wrong place to revoke a token at the provider's API, delete a remote object, or notify a third party. Nothing in the hooks' documentation said so, and `PluginCtx` exposed `transaction` but nothing to defer past it.
22
23 `PluginCtx` gains `afterCommit`. It runs the effect once the outermost transaction commits, discards it if that transaction rolls back, and runs it immediately when no transaction is active. The lifecycle hooks now document that they run inside core's transaction and that outside-world work belongs in `afterCommit`.
24
25 Sequencing work after your own `transaction(...)` call is not equivalent, and the documentation says so explicitly: `transaction` nests by pass-through, so inside an active transaction the inner call simply runs its effect and "afterwards" is still before any commit.
26
27- [#1569](https://github.com/UsefulSoftwareCo/executor/pull/1569) [`d874455`](https://github.com/UsefulSoftwareCo/executor/commit/d874455c5d5ea83a69e2010152aeb703d74f51c2) Thanks [@GeiserX](https://github.com/GeiserX)! - **Abandoned authorization sessions no longer keep their PKCE verifier forever**
28
29 An OAuth authorization session stores its PKCE verifier so the callback can redeem the code. `complete` discarded an expired session lazily, but an _abandoned_ flow is never completed, so that check never ran for it and nothing else swept the table — the verifier sat there in plaintext indefinitely.
30
31 Starting a new authorization now sweeps sessions that have already expired. Doing it on `start` bounds the table by how often authorization is begun rather than by how often it is abandoned, and needs no scheduler in any host. A session whose completion cannot be retried is dropped rather than left behind.
32
33 The sweep only ever reaches rows the caller can already see, so one member's authorization never touches another member's sessions. It is best-effort: a sweep that fails logs a warning and lets the authorization continue.
34
35- [#1825](https://github.com/UsefulSoftwareCo/executor/pull/1825) [`06a7b75`](https://github.com/UsefulSoftwareCo/executor/commit/06a7b75fb62ac1c3eb22e28154fc250cd32a3ccb) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **A console URL naming an organization you cannot see is a not-found page, every time**
36
37 Opening `/<some-other-slug>/policies` sometimes rendered the full authenticated console — sidebar, org switcher showing your OWN organization, page chrome — under an address naming an organization you are not a member of. The page body was a failing org-scoped query with a Retry button, so the workspace on screen belonged to nobody and the URL belonged to someone else.
38
39 The shell's not-found only fired once `/account/me` had answered for the URL's slug. Until then the console read its identity from the auth-hint cookie, which always names the organization the session last landed in, never the one in the address bar. So the first paint answered a question about a different organization and built a whole workspace out of it, and whether you ever saw that depended on how fast the server replied.
40
41 The shell is now built only from an answer that names the organization the URL names. A slug the current answer does not cover renders nothing at all until `/account/me` resolves for that slug, and then either the workspace or — for an organization this session cannot see — the not-found page. The URL is never rewritten: a wrong address stays a wrong address.
42
43 The ordinary cold load is untouched. The hint names the slug already in the URL, so it matches on the very first paint and the shell renders with no round trip. Only a slug the hint does not name waits: a foreign one, and the single frame after switching organizations, which now paints the organization the URL asked for instead of briefly showing the previous one.
44
45- [#1575](https://github.com/UsefulSoftwareCo/executor/pull/1575) [`e5526f3`](https://github.com/UsefulSoftwareCo/executor/commit/e5526f32b355e56aabe20024bc2f96296bfa982d) Thanks [@GeiserX](https://github.com/GeiserX)! - **GraphQL introspection no longer logs a credential carried in the endpoint URL**
46
47 `query` is a supported credential carrier, so a GraphQL endpoint can be reached with `?token=<secret>`. Introspection built its request from a URL **string**, and `HttpClientRequest.setUrl` keeps a string verbatim as `request.url`. Every `HttpClientError` renders `${method} ${request.url}` into its `message` getter, and introspection logs the raw failure cause — so on any transport failure or non-JSON response, the connection's secret was written to the process log.
48
49 The request is now built from a URL **object**, which moves the query into `request.urlParams` and clears it from `request.url`. The secret is therefore absent from the error message, and from anything else that renders the request URL. The credential still reaches the upstream: the client recombines url and urlParams when it executes the request. The endpoint's own query string is handled the same way, not just the separately-supplied query parameters, since a configured endpoint can carry a credential too.
50
51 **The query string is now normalized on the wire.** Recombination appends each pair through `URLSearchParams`, so the query is re-serialized in form-urlencoded form instead of passed through byte-for-byte:
52 - a space written as `%20` is sent as `+`
53 - `~` and `!'()` are percent-encoded
54 - a valueless `?flag` is sent as `flag=`
55
56 Key order, repeated keys, and already-encoded reserved characters are unchanged, and every parameter still decodes to the same value. This is not avoidable while the fix holds: raw query bytes only survive inside `request.url`, which is the one field every error message renders, so byte-transparency and keeping the credential out of the log cannot both hold. An upstream that signs its raw query string is the case to watch. The exact resulting URLs are pinned by test.
57
58 Two endpoints are now rejected up front with an `invalid-endpoint` failure rather than dialed:
59 - an endpoint that is not a valid URL, which cannot be split this way and would otherwise be sent without the query parameters it was asked to include
60 - an endpoint carrying userinfo (`https://user:pass@host/…`), which `URL` keeps in the origin, so it would stay in `request.url` and leak into error messages exactly the way a query-carried secret used to
61
62 Neither rejection echoes any part of the endpoint. A health check on such an integration now reports the invalid configuration and points the operator at the endpoint URL, instead of blaming the credential that was never sent.
63
64- [#1596](https://github.com/UsefulSoftwareCo/executor/pull/1596) [`b77ee69`](https://github.com/UsefulSoftwareCo/executor/commit/b77ee69aeeb90e40a2902c4d849e89d2343d91de) Thanks [@GeiserX](https://github.com/GeiserX)! - **Credentials are kept out of the health-check result that gets persisted**
65
66 A health check stores a sample of the probed operation's response body, plus the extracted identity, in `connection.last_health` — so whatever those carry is written to the database. The operation is user-chosen from the plugin's catalog, which means it can just as easily be a key-listing endpoint as a `/me`, and those return secrets that no scrub of the connection's own credential value can recognise, because they are different secrets entirely.
67
68 Two passes now cover both kinds of secret:
69 - **By key name.** Leaves whose key names a credential (`token`, `api_key`, `secret`, `authorization`, `session`, …) have their value replaced with `[redacted]`. The row itself is kept, so the live preview still shows the response shape and the identity picker still works. Keys that merely contain a matching substring, such as `author`, are left alone. camelCase spellings are recognised too: `accessToken`, `refreshToken`, `clientSecret`, `privateKey` and `sessionId` have no separator before the credential word, so a matcher that only looks for one reads them as innocent.
70 - **By value.** The OpenAPI health check removes the connection's own credential value from each sampled value, covering the other direction: a body that echoes back the key it was authenticated with under an innocent-looking name. This runs before the sample's 120-char truncation, not after — truncating first leaves a prefix of a long credential that an exact-value scrub can no longer match, and that prefix is what would be persisted.
71
72 The key check reads a dotted path two ways. It uses the nearest NAMED segment, because array elements are named by index: `{"tokens": ["sk-live-…"]}` produces the path `tokens.0`, and testing the literal `"0"` matches nothing. It also uses an enclosing array container, because a key listing returns `{"api_keys": [{"value": "sk-live-…"}]}`, whose path is `api_keys.0.value` — the nearest named segment there is the innocent `value`, and only the array's own key says what the collection holds. A collection whose key names nothing, such as `names.0`, is still shown in full.
73
74 The extracted `identity` goes through both passes as well. It is read straight off the raw body, so it previously bypassed them even though it is persisted the same way, and `identityField` is user-chosen from whatever the picker listed.
75
76- [#1823](https://github.com/UsefulSoftwareCo/executor/pull/1823) [`d74865f`](https://github.com/UsefulSoftwareCo/executor/commit/d74865ff8cb7c4ada1badac512169beafe925cf8) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **Saved integrations come back after an upgrade left an OAuth expiry in the old number format**
77
78 Some installs lost every saved integration from the MCP gateway at once. The credentials were never deleted — the gateway simply could not read the table they live in, so it served an empty tool list and restarting did not help.
79
80 The `connection.expires_at` column records when an OAuth access token expires. It used to be a plain number; it now holds the value's digits, because a millisecond timestamp is larger than a 32-bit integer. SQLite does not rewrite rows when a column's type changes, so a connection saved by an older build still held the old form. Reading one back failed, and because the failure happened while mapping the row, it failed the whole query rather than that one field — one stale row was enough to hide every integration.
81
82 A boot-time migration now converts those values to the current form. It runs before anything reads the table, so the integrations are back on the first restart after upgrading. It only touches values still in the old numeric form: rows already written by a current build are left exactly as they are, and it runs once.
83
84- [#1607](https://github.com/UsefulSoftwareCo/executor/pull/1607) [`75c917f`](https://github.com/UsefulSoftwareCo/executor/commit/75c917fdb0cb8499678f842c62133483472b4814) Thanks [@timkley](https://github.com/timkley)! - **Fix: allow MCP integrations to declare OAuth scopes when resource metadata omits them**
85
86 MCP OAuth methods can now carry an optional non-empty scope list. Declared scopes
87 take precedence over protected-resource scope discovery, so servers with fixed
88 scopes can connect even when their dynamically registered OAuth client has no
89 resource identifier. Existing integrations without declared scopes keep
90 discovering them from the server at connect time.
91
92- [#1577](https://github.com/UsefulSoftwareCo/executor/pull/1577) [`4879d47`](https://github.com/UsefulSoftwareCo/executor/commit/4879d47bd7bc0d80440fe0438ce0e4b36b19a2d2) Thanks [@GeiserX](https://github.com/GeiserX)! - **Idle MCP connections age out on the pool's next acquire, even when their identity is never dialled again**
93
94 The pool's five-minute idle window was only consulted against the entry being requested, so an identity that was never asked for a second time was never examined a second time. Its session stayed open and authenticated for as long as the pool lived, holding the bearer token or API key it was dialled with. The advertised bound applied only to connections that happened to be reused.
95
96 `acquire` now sweeps every entry past the window, closing each one, rather than just the entry matching the key. This stays lazy in the sense the pool intends — activity drives it, there is no timer and no background fiber — and the map holds at most one entry per identity, so the scan is trivial.
97
98 Because the sweep is paid for by whichever invocation acquires next, it cannot be allowed to stall that caller. The expired entries leave the pool synchronously, before any close is awaited, and the closes then run concurrently with each one bounded by a two-second timeout — so a server that accepts a close and goes quiet is abandoned rather than waited on, and cannot hold up an unrelated request or the connections queued behind it.
99
100 Reuse is unchanged: an entry still inside the window is left alone, and a second call for the same identity still gets the parked session rather than a fresh dial.
101
102- [#1821](https://github.com/UsefulSoftwareCo/executor/pull/1821) [`435c0f2`](https://github.com/UsefulSoftwareCo/executor/commit/435c0f2d36ee891158a4e5cec35024cf439af6fe) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **Fix: add remote MCP servers that sit behind an authenticating proxy**
103
104 The add-MCP form now carries an optional request headers editor. The name/value
105 pairs are sent on the connection check and on every later request, so an
106 endpoint gated by an edge authenticator — a Cloudflare Access service token,
107 for example — can be discovered and added.
108
109 A `403` from such a gate is also no longer read as an unreachable server. It is
110 classified the same way a `401` is: the endpoint needs credentials, so the add
111 flow continues to the auth step instead of stopping on "Couldn't reach this
112 URL".
113
114- [#1775](https://github.com/UsefulSoftwareCo/executor/pull/1775) [`ecb87de`](https://github.com/UsefulSoftwareCo/executor/commit/ecb87debfcaa6676062cc09b8c847fde330f6337) Thanks [@The-AarushiSingh](https://github.com/The-AarushiSingh)! - **Stdio MCP integrations can be edited from the UI**
115
116 The integration Edit sheet showed stdio servers as read-only text and told you
117 to remove and recreate the integration to change its command. Fixing a typo in
118 an argument, moving a server to a new path, or adding a static environment
119 variable meant editing `executor.jsonc` by hand, or losing the integration's
120 connections and tool policies to a delete-and-re-add.
121
122 The sheet now edits the command, its arguments, the working directory, and the
123 declared environment map, staged and applied by the sheet's own Save like the
124 remote editor beside it. Arguments use the same quote-aware parsing as the add
125 flow, so an argument containing spaces survives a round trip.
126
127 The environment field edits the DECLARED static variables only. A stdio server
128 receives those plus a small fixed base set — it does not inherit executor's
129 environment — and secret values still belong to the connection, entered per
130 account against the server's declared `stdio_env` method.
131
132 Saving revises the integration config, which is already enough to rebuild the
133 tool catalog: connections whose catalog predates the revision re-list on their
134 next read, so an edited command's tools are correct without an explicit
135 refresh.
136
137- [#1402](https://github.com/UsefulSoftwareCo/executor/pull/1402) [`742a144`](https://github.com/UsefulSoftwareCo/executor/commit/742a144f169e24d5e0c082bfebb4334106267962) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **A disabled upstream API now reports `misconfigured` instead of `expired`**
138
139 A 403 caused by the provider disabling the API (Google SERVICE_DISABLED / accessNotConfigured shapes) is a configuration problem, not a credential problem — reconnecting cannot fix it. Health checks now classify it as a fifth status, `misconfigured`, shown with an amber badge and a link to the provider console instead of a Reconnect prompt. Ordinary 401/403 credential rejections still report `expired`.
140
141- [#1377](https://github.com/UsefulSoftwareCo/executor/pull/1377) [`98615b4`](https://github.com/UsefulSoftwareCo/executor/commit/98615b4bd6ee8b18bc63a304fe215c76332e108f) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **A credential-store outage no longer costs an OAuth connection its grant**
142
143 Refreshing an OAuth token spends the stored refresh token: the authorization server rotates it, so the copy we sent stops working the moment the grant succeeds and the rotated one is the only thing that can mint again. Persisting the rotated token first bounds what a partial write can lose, but it cannot help when the store is refusing writes outright — the grant has already run, there is nowhere to put the successor, and every later refresh replays a token the server has revoked. The connection then reports `invalid_grant` and demands a re-auth over what was only a storage blip.
144
145 The refresh is now gated on a store that is proven writable. Before the grant runs, it writes a fixed value to an item of its own that holds no credential and sits in the same partition as the connection's tokens. A store that cannot take that write fails the resolve while the stored refresh token is still valid, so the connection recovers on its own once the store does.
146
147 The probe deliberately does not test the store by rewriting the refresh token with the value it just read. That is a read-then-write with no compare-and-set, and two instances refreshing one connection would lose the newer token to it: one reads the stored token, the other spends that same token and stores its rotated replacement, and the first then writes the spent one back over the replacement. The connection would die exactly the way the gate is meant to prevent.
148
149 The probe also removes a write rather than adding one in the common case. Authorization servers that do not rotate hand back the same refresh token, and that value is no longer re-persisted when it has not changed — a rotated token never matches, so the write that matters still happens.
150
151- [#1822](https://github.com/UsefulSoftwareCo/executor/pull/1822) [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **An OAuth app can now be registered without an RFC 8707 resource, and that absence holds on every request**
152
153 Microsoft Entra v2 rejects any authorization request that carries both a v2 `scope` (such as `https://api.fabric.microsoft.com/.default`) and the RFC 8707 `resource` parameter, failing with `AADSTS9010010` before the consent screen. Executor made that unavoidable for MCP servers behind Entra: registering an app for an MCP integration always derived the MCP endpoint as the resource, the form had no field to change it, and so every request carried the parameter Entra rejects.
154
155 The register/edit OAuth app form now shows the resource indicator. It is still prefilled for MCP servers — nothing changes for providers that accept the parameter — but it can be cleared, and a cleared value persists as "no resource". A resource-less app then omits `resource` on all four grants alike: the authorization request, the code exchange, token refresh, and client-credentials. Symmetry matters here — sending `resource` on authorize but not on the token request (or the reverse) would bind the two tokens to different audiences.
156
157 Two adjacent gaps closed with it:
158 - MCP scope discovery no longer depends on the app's resource. It now falls back to the integration's own discovery URL (the MCP endpoint), so clearing the resource does not break connecting.
159 - Token refresh for a first-party OAuth app dropped the app's configured resource, refreshing to a different audience than the original grant. It now sends the same resource the authorization request sent.
160
161 Apps that keep their resource — the default for every discovered MCP server — behave exactly as before: the parameter is sent on every grant, as the MCP authorization spec expects.
162
163- [#1567](https://github.com/UsefulSoftwareCo/executor/pull/1567) [`6225d5e`](https://github.com/UsefulSoftwareCo/executor/commit/6225d5ede05b23f552211ad0a99267f4b94fcaf6) Thanks [@GeiserX](https://github.com/GeiserX)! - **Keep token material out of OAuth token-endpoint error messages**
164
165 A token-endpoint failure renders a preview of the upstream body into its
166 message, and that message is persisted onto connection health, returned to the
167 caller, and carried into telemetry. On a malformed HTTP 200 the body being
168 previewed is a _successful_ token response, so an access token and a refresh
169 token could be rendered into it.
170
171 The preview is now built from an allowlist of fields that are safe to show
172 (`error`, `errors`, `error_description`, `error_uri`, plus `code`, `message`,
173 and `detail` nested inside them) instead of a denylist of fields to hide. A
174 field nobody anticipated is omitted by default rather than printed by default.
175 Keys stay visible and only non-allowlisted string values are replaced, so an
176 operator can still read the shape of what the server sent. `code` is readable
177 only when nested, because at the top level of a token response it is the RFC
178 6749 authorization code.
179
180 Form-encoded bodies take the same allowlist, the walk over a body is
181 depth-bounded, and the failure summary records the token endpoint's hostname
182 rather than its full URL, which can carry identifiers in its path.
183
184 On that same malformed-200 path the failure no longer keeps the underlying
185 rejection as its `cause`. That rejection carries the parsed token response, so
186 keeping it put the raw tokens back into anything that renders the whole failure
187 rather than only its message. Everything the path needs from the body — the
188 status, the error code, the redacted preview — is read before the failure is
189 built. A transport failure still keeps its cause, which is what tells a DNS miss
190 apart from a refused connection.
191
192 No public API changes. The dead-grant classification added for HTTP 200 refresh
193 refusals is unaffected: it reads the HTTP status, not the rendered preview.
194
195- [#1829](https://github.com/UsefulSoftwareCo/executor/pull/1829) [`369fa0a`](https://github.com/UsefulSoftwareCo/executor/commit/369fa0a32d5800c8333d2be00610c89f5feeb9ae) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **The 1Password provider can now be scoped to several vaults, with explicit per-vault addressing**
196
197 The provider previously bound exactly one vault. The configuration now holds a set of vaults selected with checkboxes, and every reference is explicit about which vault it means: the item picker is a searchable list that shows each item's vault and stores a vault-qualified `op://` reference, so identically-titled items in different vaults can never collide. A bare item name is accepted only when it matches exactly one item across the selected vaults — a name that exists in more than one place fails with an error naming the matching vaults instead of silently picking one.
198
199 Reopening the vault or item pickers no longer flashes a loading state: listings are retained and re-validated in the background, so the last-known list renders instantly.
200
201 Configurations saved before this change keep working: the stored single-vault shape is read as a one-vault list and upgrades to the new shape the next time it is saved. The `status` tool reports `vaultNames` for all configured vaults and flags any configured vault the account can no longer see. Provider entries also gained an optional `group` label, which pickers use to show where an item lives.
202
203- [#1772](https://github.com/UsefulSoftwareCo/executor/pull/1772) [`597ce90`](https://github.com/UsefulSoftwareCo/executor/commit/597ce90b30b96d2dd333a6c34e5f2cd0ee4c7d42) Thanks [@baggiiiie](https://github.com/baggiiiie)! - Persist the Connect-an-agent card's transport, artifact, integration-search, and approval preferences in the browser so its generated MCP install command remains stable across page reloads.
204
205- [#1529](https://github.com/UsefulSoftwareCo/executor/pull/1529) [`0004ea3`](https://github.com/UsefulSoftwareCo/executor/commit/0004ea353411c9806273698e42d95ab45e0ba2f9) Thanks [@jadch](https://github.com/jadch)! - Keep Last-Event-ID recovery scoped to its originating MCP stream.
206
207- [#1441](https://github.com/UsefulSoftwareCo/executor/pull/1441) [`a9bf623`](https://github.com/UsefulSoftwareCo/executor/commit/a9bf623dd4de359ca1d87275973b6ddf8b4f0ea6) Thanks [@salmonumbrella](https://github.com/salmonumbrella)! - Self-hosted instances can now allow additional browser origins without changing
208 their canonical public URL. Set `EXECUTOR_TRUSTED_ORIGINS` to a comma-separated
209 list of exact HTTP or HTTPS origins when one instance is intentionally reachable
210 through multiple hostnames or addresses. OAuth callbacks, MCP metadata, approval
211 links, and other generated URLs remain pinned to `EXECUTOR_WEB_BASE_URL`, and
212 origins are never inferred from request headers.
213
214- [#1720](https://github.com/UsefulSoftwareCo/executor/pull/1720) [`2da4953`](https://github.com/UsefulSoftwareCo/executor/commit/2da49535562e27291a1544f10e12b079b41f0362) Thanks [@Zeko369](https://github.com/Zeko369)! - **Connect an integration from the sidebar**
215
216 The sidebar lists your integrations on every console route, but connecting
217 another one meant navigating back to the integrations page to reach its Connect
218 action — the picker state was owned by that page, so the shared shell could
219 render the list without being able to open the flow behind it.
220
221 The connect dialog now belongs to the shell. A labelled plus button sits beside
222 the sidebar's Integrations heading and opens the same picker, records the same
223 event, and leaves the current route in place behind it. On mobile the navigation
224 drawer closes first so the dialog gets the full viewport.
225
226- [#1824](https://github.com/UsefulSoftwareCo/executor/pull/1824) [`97ff388`](https://github.com/UsefulSoftwareCo/executor/commit/97ff38856c1618cfe8b6dc4394d3761d70b076b6) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **Tools reads stop waiting on slow upstream servers**
227
228 A tools read rebuilds every connection whose catalog has gone stale before answering. The rebuilds already ran concurrently, but the read still waited for all of them, so one slow or unreachable MCP server gated every catalog read behind its network timeout — a tools listing could take tens of seconds while healthy connections sat ready.
229
230 A read now waits at most a short grace budget (2 seconds by default) for the rebuilds, then answers from the persisted catalog. The rebuilds keep running after the read returns and land on a later read, so the catalog still converges — it just no longer holds the reader hostage while it does. Overlapping reads share one in-flight rebuild per connection instead of stacking new ones.
231
232 The budget is `toolsSyncGraceMs` on the SDK config. Pass `null` to restore the strict behavior, where a read blocks until every rebuild finishes and always reflects a fully converged catalog.
233
234- [#1819](https://github.com/UsefulSoftwareCo/executor/pull/1819) [`1cd81d6`](https://github.com/UsefulSoftwareCo/executor/commit/1cd81d62cefa6fb8cfa2e21f2c0adbaedee60041) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **Fix: stop the update check from claiming a newer version is available on builds it cannot compare**
235
236 A build stamped with the placeholder 0.0.0 version always compared as older
237 than the latest release, and a prerelease on a channel with no matching
238 dist-tag (rc, alpha, and similar) always lost the comparison too. Both cases
239 now short-circuit to "no update available" before the check reaches the
240 registry.
241
242 This applies wherever the update check runs, so the CLI check and the sidebar
243 update card both stop showing an update prompt that a user could never act on.
244
245- Updated dependencies [[`1908dd6`](https://github.com/UsefulSoftwareCo/executor/commit/1908dd6d7611489362d451f7594adca542c13ba1), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
246 - @executor-js/local@1.6.3
247 - @executor-js/sdk@1.6.3
248 - @executor-js/api@1.4.66
249 - @executor-js/runtime-quickjs@1.6.3
250
3## 1.6.2251## 1.6.2
4 252
5### Patch Changes253### Patch Changes
apps/cli/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "executor",2 "name": "executor",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "private": true,4 "private": true,
5 "bin": {5 "bin": {
6 "executor": "./bin/executor.ts"6 "executor": "./bin/executor.ts"
apps/cloud/CHANGELOG.md+41−0
@@ -1,5 +1,46 @@
1# @executor-js/cloud1# @executor-js/cloud
2 2
3## 1.4.64
4
5### Patch Changes
6
7- [#1806](https://github.com/UsefulSoftwareCo/executor/pull/1806) [`93817ed`](https://github.com/UsefulSoftwareCo/executor/commit/93817ed43919934092a4706327f50f6adfd14e47) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **Team pricing is per member with unlimited executions**
8
9 The Team plan moves from $150 per organization with a 250,000-execution
10 allowance to $15 per member per month with unlimited executions. The
11 `members` feature is unarchived in `autumn.config.ts` and billed in arrears
12 on the seat count the app reports; Free keeps its 3-member, 100,000-execution
13 shape and Enterprise stays custom with seat usage tracked for visibility.
14
15 Seat counts reconcile from a full WorkOS recount (active members only —
16 pending invites hold a seat for the plan gate but are not billed) after
17 member removal, invitation acceptance, organization creation, and on every
18 login callback, which also picks up joins the app never sees a mutation for
19 (SSO JIT provisioning, join by domain, dashboard edits). Plans that predate
20 seat pricing have no members balance and are skipped, so existing
21 subscriptions keep billing exactly as before on their current plan version.
22
23 The plans page, billing page, and marketing pricing cards now show the
24 per-member price.
25
26- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946), [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f), [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad), [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
27 - @executor-js/react@1.4.66
28 - @executor-js/plugin-mcp@1.6.3
29 - @executor-js/sdk@1.6.3
30 - @executor-js/plugin-openapi@1.6.3
31 - @executor-js/fumadb@1.5.8
32 - @executor-js/mcp-apps-shell@1.4.14
33 - @executor-js/plugin-graphql@1.6.3
34 - @executor-js/plugin-toolkits@1.5.38
35 - @executor-js/plugin-workos-vault@0.0.2
36 - @executor-js/api@1.4.66
37 - @executor-js/execution@1.6.3
38 - @executor-js/vite-plugin@0.0.63
39 - @executor-js/cloudflare@0.0.45
40 - @executor-js/host-mcp@1.4.4
41 - @executor-js/runtime-dynamic-worker@1.4.4
42 - @executor-js/runtime-quickjs@1.6.3
43
3## 1.4.6344## 1.4.63
4 45
5### Patch Changes46### Patch Changes
apps/cloud/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/cloud",2 "name": "@executor-js/cloud",
3 "version": "1.4.63",3 "version": "1.4.64",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "scripts": {6 "scripts": {
apps/desktop/CHANGELOG.md+2−0
@@ -1,5 +1,7 @@
1# @executor-js/desktop1# @executor-js/desktop
2 2
3## 1.6.3
4
3## 1.6.25## 1.6.2
4 6
5## 1.6.17## 1.6.1
apps/desktop/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/desktop",2 "name": "@executor-js/desktop",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "private": true,4 "private": true,
5 "homepage": "https://github.com/UsefulSoftwareCo/executor",5 "homepage": "https://github.com/UsefulSoftwareCo/executor",
6 "license": "MIT",6 "license": "MIT",
apps/host-selfhost/CHANGELOG.md+22−0
@@ -1,5 +1,27 @@
1# @executor-js/host-selfhost1# @executor-js/host-selfhost
2 2
3## 0.0.45
4
5### Patch Changes
6
7- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946), [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f), [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad), [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/react@1.4.66
9 - @executor-js/plugin-mcp@1.6.3
10 - @executor-js/sdk@1.6.3
11 - @executor-js/plugin-openapi@1.6.3
12 - @executor-js/fumadb@1.5.8
13 - @executor-js/app@1.4.4
14 - @executor-js/mcp-apps-shell@1.4.14
15 - @executor-js/plugin-graphql@1.6.3
16 - @executor-js/plugin-toolkits@1.5.38
17 - @executor-js/analytics@0.1.10
18 - @executor-js/api@1.4.66
19 - @executor-js/execution@1.6.3
20 - @executor-js/host-mcp@1.4.4
21 - @executor-js/plugin-encrypted-secrets@0.0.45
22 - @executor-js/plugin-provider-service-split@0.0.17
23 - @executor-js/runtime-quickjs@1.6.3
24
3## 0.0.4425## 0.0.44
4 26
5### Patch Changes27### Patch Changes
apps/host-selfhost/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/host-selfhost",2 "name": "@executor-js/host-selfhost",
3 "version": "0.0.44",3 "version": "0.0.45",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
apps/local/CHANGELOG.md+34−0
@@ -1,5 +1,39 @@
1# @executor-js/local1# @executor-js/local
2 2
3## 1.6.3
4
5### Patch Changes
6
7- [#1458](https://github.com/UsefulSoftwareCo/executor/pull/1458) [`1908dd6`](https://github.com/UsefulSoftwareCo/executor/commit/1908dd6d7611489362d451f7594adca542c13ba1) Thanks [@tylergibbs1](https://github.com/tylergibbs1)! - **An unsupported method probed before `initialize` no longer kills the MCP connection**
8
9 Only `initialize` can open a session, so the streamable-HTTP transport answered every other pre-session method with HTTP 400 + `-32000 Server not initialized`. A 400 is a transport-level failure, so clients dropped the connection instead of treating it as one request failing — a client that opens with an optional probe (MCP 2026-07-28 clients lead with `server/discover`) was disconnected before it could fall back to `initialize`. Over `executor mcp`, which bridges this endpoint to stdio, that closed the client's pipe outright.
10
11 Pre-session dispatch now answers any method other than `initialize` with `-32601 Method not found` on a normal 200, which is a per-request error, so the connection survives and the handshake proceeds. This replaces only that one answer: a POST with a bad `Accept` or `Content-Type` still gets the transport's 406 or 415, and a message that is not a valid JSON-RPC request still gets its parse error.
12
13- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946), [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f), [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad), [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
14 - @executor-js/react@1.4.66
15 - @executor-js/plugin-mcp@1.6.3
16 - @executor-js/sdk@1.6.3
17 - @executor-js/plugin-openapi@1.6.3
18 - @executor-js/fumadb@1.5.8
19 - @executor-js/app@1.4.4
20 - @executor-js/mcp-apps-shell@1.4.14
21 - @executor-js/plugin-graphql@1.6.3
22 - @executor-js/plugin-onepassword@1.6.3
23 - @executor-js/plugin-toolkits@1.5.38
24 - @executor-js/analytics@0.1.10
25 - @executor-js/api@1.4.66
26 - @executor-js/config@1.6.3
27 - @executor-js/execution@1.6.3
28 - @executor-js/vite-plugin@0.0.63
29 - @executor-js/host-mcp@1.4.4
30 - @executor-js/plugin-desktop-settings@1.6.3
31 - @executor-js/plugin-example@1.6.3
32 - @executor-js/plugin-file-secrets@1.6.3
33 - @executor-js/plugin-keychain@1.6.3
34 - @executor-js/plugin-provider-service-split@0.0.17
35 - @executor-js/runtime-quickjs@1.6.3
36
3## 1.6.237## 1.6.2
4 38
5### Patch Changes39### Patch Changes
apps/local/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/local",2 "name": "@executor-js/local",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
bun.lock+33−33
@@ -31,7 +31,7 @@ · 30 unmodified lines
31 },31 },
32 "apps/cli": {32 "apps/cli": {
33 "name": "executor",33 "name": "executor",
34 "version": "1.6.2",34 "version": "1.6.3",
35 "bin": {35 "bin": {
36 "executor": "./bin/executor.ts",36 "executor": "./bin/executor.ts",
37 },37 },
@@ -60,7 +60,7 @@ · 22 unmodified lines
60 },60 },
61 "apps/cloud": {61 "apps/cloud": {
62 "name": "@executor-js/cloud",62 "name": "@executor-js/cloud",
63 "version": "1.4.63",63 "version": "1.4.64",
64 "dependencies": {64 "dependencies": {
65 "@cloudflare/vite-plugin": "^1.31.1",65 "@cloudflare/vite-plugin": "^1.31.1",
66 "@effect/atom-react": "catalog:",66 "@effect/atom-react": "catalog:",
@@ -133,7 +133,7 @@ · 66 unmodified lines
133 },133 },
134 "apps/desktop": {134 "apps/desktop": {
135 "name": "@executor-js/desktop",135 "name": "@executor-js/desktop",
136 "version": "1.6.2",136 "version": "1.6.3",
137 "dependencies": {137 "dependencies": {
138 "@sentry/bun": "^10.57.0",138 "@sentry/bun": "^10.57.0",
139 "@sentry/electron": "^7.13.0",139 "@sentry/electron": "^7.13.0",
@@ -220,7 +220,7 @@ · 80 unmodified lines
220 },220 },
221 "apps/host-selfhost": {221 "apps/host-selfhost": {
222 "name": "@executor-js/host-selfhost",222 "name": "@executor-js/host-selfhost",
223 "version": "0.0.44",223 "version": "0.0.45",
224 "dependencies": {224 "dependencies": {
225 "@better-auth/api-key": "^1.6.11",225 "@better-auth/api-key": "^1.6.11",
226 "@cloudflare/worker-bundler": "0.2.1",226 "@cloudflare/worker-bundler": "0.2.1",
@@ -272,7 +272,7 @@ · 45 unmodified lines
272 },272 },
273 "apps/local": {273 "apps/local": {
274 "name": "@executor-js/local",274 "name": "@executor-js/local",
275 "version": "1.6.2",275 "version": "1.6.3",
276 "dependencies": {276 "dependencies": {
277 "@effect/atom-react": "catalog:",277 "@effect/atom-react": "catalog:",
278 "@effect/platform-node": "catalog:",278 "@effect/platform-node": "catalog:",
@@ -352,7 +352,7 @@ · 73 unmodified lines
352 },352 },
353 "e2e": {353 "e2e": {
354 "name": "@executor-js/e2e",354 "name": "@executor-js/e2e",
355 "version": "0.0.42",355 "version": "0.0.43",
356 "dependencies": {356 "dependencies": {
357 "@executor-js/api": "workspace:*",357 "@executor-js/api": "workspace:*",
358 "@executor-js/emulate": "^0.14.1",358 "@executor-js/emulate": "^0.14.1",
@@ -387,7 +387,7 @@ · 28 unmodified lines
387 },387 },
388 "examples/all-plugins": {388 "examples/all-plugins": {
389 "name": "@executor-js/example-all-plugins",389 "name": "@executor-js/example-all-plugins",
390 "version": "0.0.63",390 "version": "0.0.64",
391 "dependencies": {391 "dependencies": {
392 "@executor-js/plugin-file-secrets": "workspace:*",392 "@executor-js/plugin-file-secrets": "workspace:*",
393 "@executor-js/plugin-graphql": "workspace:*",393 "@executor-js/plugin-graphql": "workspace:*",
@@ -406,7 +406,7 @@ · 12 unmodified lines
406 },406 },
407 "examples/docs-sdk-quickstart": {407 "examples/docs-sdk-quickstart": {
408 "name": "@executor-js/example-docs-sdk-quickstart",408 "name": "@executor-js/example-docs-sdk-quickstart",
409 "version": "0.0.48",409 "version": "0.0.49",
410 "dependencies": {410 "dependencies": {
411 "@executor-js/plugin-openapi": "workspace:*",411 "@executor-js/plugin-openapi": "workspace:*",
412 "@executor-js/sdk": "workspace:*",412 "@executor-js/sdk": "workspace:*",
@@ -463,7 +463,7 @@ · 50 unmodified lines
463 },463 },
464 "packages/core/analytics": {464 "packages/core/analytics": {
465 "name": "@executor-js/analytics",465 "name": "@executor-js/analytics",
466 "version": "0.1.9",466 "version": "0.1.10",
467 "dependencies": {467 "dependencies": {
468 "@effect/platform-node": "catalog:",468 "@effect/platform-node": "catalog:",
469 "@executor-js/execution": "workspace:*",469 "@executor-js/execution": "workspace:*",
@@ -479,7 +479,7 @@ · 9 unmodified lines
479 },479 },
480 "packages/core/api": {480 "packages/core/api": {
481 "name": "@executor-js/api",481 "name": "@executor-js/api",
482 "version": "1.4.65",482 "version": "1.4.66",
483 "dependencies": {483 "dependencies": {
484 "@executor-js/execution": "workspace:*",484 "@executor-js/execution": "workspace:*",
485 "@executor-js/host-mcp": "workspace:*",485 "@executor-js/host-mcp": "workspace:*",
@@ -496,7 +496,7 @@ · 10 unmodified lines
496 },496 },
497 "packages/core/cli": {497 "packages/core/cli": {
498 "name": "@executor-js/cli",498 "name": "@executor-js/cli",
499 "version": "0.2.52",499 "version": "0.2.53",
500 "bin": {500 "bin": {
501 "executor-sdk": "./dist/index.js",501 "executor-sdk": "./dist/index.js",
502 },502 },
@@ -517,7 +517,7 @@ · 14 unmodified lines
517 },517 },
518 "packages/core/config": {518 "packages/core/config": {
519 "name": "@executor-js/config",519 "name": "@executor-js/config",
520 "version": "1.6.2",520 "version": "1.6.3",
521 "dependencies": {521 "dependencies": {
522 "@executor-js/sdk": "workspace:*",522 "@executor-js/sdk": "workspace:*",
523 "jiti": "^2.6.1",523 "jiti": "^2.6.1",
@@ -538,7 +538,7 @@ · 14 unmodified lines
538 },538 },
539 "packages/core/execution": {539 "packages/core/execution": {
540 "name": "@executor-js/execution",540 "name": "@executor-js/execution",
541 "version": "1.6.2",541 "version": "1.6.3",
542 "dependencies": {542 "dependencies": {
543 "@executor-js/codemode-core": "workspace:*",543 "@executor-js/codemode-core": "workspace:*",
544 "@executor-js/sdk": "workspace:*",544 "@executor-js/sdk": "workspace:*",
@@ -559,7 +559,7 @@ · 14 unmodified lines
559 },559 },
560 "packages/core/fumadb": {560 "packages/core/fumadb": {
561 "name": "@executor-js/fumadb",561 "name": "@executor-js/fumadb",
562 "version": "1.5.7",562 "version": "1.5.8",
563 "dependencies": {563 "dependencies": {
564 "@clack/prompts": "^1.3.0",564 "@clack/prompts": "^1.3.0",
565 "@paralleldrive/cuid2": "^3.3.0",565 "@paralleldrive/cuid2": "^3.3.0",
@@ -604,7 +604,7 @@ · 38 unmodified lines
604 },604 },
605 "packages/core/sdk": {605 "packages/core/sdk": {
606 "name": "@executor-js/sdk",606 "name": "@executor-js/sdk",
607 "version": "1.6.2",607 "version": "1.6.3",
608 "dependencies": {608 "dependencies": {
609 "@executor-js/fumadb": "workspace:*",609 "@executor-js/fumadb": "workspace:*",
610 "@standard-schema/spec": "^1.1.0",610 "@standard-schema/spec": "^1.1.0",
@@ -657,7 +657,7 @@ · 46 unmodified lines
657 },657 },
658 "packages/core/vite-plugin": {658 "packages/core/vite-plugin": {
659 "name": "@executor-js/vite-plugin",659 "name": "@executor-js/vite-plugin",
660 "version": "0.0.62",660 "version": "0.0.63",
661 "dependencies": {661 "dependencies": {
662 "@executor-js/sdk": "workspace:*",662 "@executor-js/sdk": "workspace:*",
663 "jiti": "^2.6.1",663 "jiti": "^2.6.1",
@@ -677,7 +677,7 @@ · 13 unmodified lines
677 },677 },
678 "packages/hosts/cloudflare": {678 "packages/hosts/cloudflare": {
679 "name": "@executor-js/cloudflare",679 "name": "@executor-js/cloudflare",
680 "version": "0.0.44",680 "version": "0.0.45",
681 "dependencies": {681 "dependencies": {
682 "@executor-js/api": "workspace:*",682 "@executor-js/api": "workspace:*",
683 "@executor-js/execution": "workspace:*",683 "@executor-js/execution": "workspace:*",
@@ -718,7 +718,7 @@ · 34 unmodified lines
718 },718 },
719 "packages/hosts/mcp-apps-shell": {719 "packages/hosts/mcp-apps-shell": {
720 "name": "@executor-js/mcp-apps-shell",720 "name": "@executor-js/mcp-apps-shell",
721 "version": "1.4.13",721 "version": "1.4.14",
722 "dependencies": {722 "dependencies": {
723 "@executor-js/react": "workspace:*",723 "@executor-js/react": "workspace:*",
724 "@executor-js/runtime-quickjs": "workspace:*",724 "@executor-js/runtime-quickjs": "workspace:*",
@@ -756,7 +756,7 @@ · 31 unmodified lines
756 },756 },
757 "packages/kernel/core": {757 "packages/kernel/core": {
758 "name": "@executor-js/codemode-core",758 "name": "@executor-js/codemode-core",
759 "version": "1.6.2",759 "version": "1.6.3",
760 "dependencies": {760 "dependencies": {
761 "@babel/parser": "^7.29.2",761 "@babel/parser": "^7.29.2",
762 "@standard-schema/spec": "^1.0.0",762 "@standard-schema/spec": "^1.0.0",
@@ -829,7 +829,7 @@ · 66 unmodified lines
829 },829 },
830 "packages/kernel/runtime-quickjs": {830 "packages/kernel/runtime-quickjs": {
831 "name": "@executor-js/runtime-quickjs",831 "name": "@executor-js/runtime-quickjs",
832 "version": "1.6.2",832 "version": "1.6.3",
833 "dependencies": {833 "dependencies": {
834 "@executor-js/codemode-core": "workspace:*",834 "@executor-js/codemode-core": "workspace:*",
835 "quickjs-emscripten": "catalog:",835 "quickjs-emscripten": "catalog:",
@@ -849,7 +849,7 @@ · 13 unmodified lines
849 },849 },
850 "packages/kernel/runtime-workerd-subprocess": {850 "packages/kernel/runtime-workerd-subprocess": {
851 "name": "@executor-js/runtime-workerd-subprocess",851 "name": "@executor-js/runtime-workerd-subprocess",
852 "version": "0.0.17",852 "version": "0.0.18",
853 "dependencies": {853 "dependencies": {
854 "@executor-js/codemode-core": "workspace:*",854 "@executor-js/codemode-core": "workspace:*",
855 "effect": "catalog:",855 "effect": "catalog:",
@@ -864,7 +864,7 @@ · 8 unmodified lines
864 },864 },
865 "packages/plugins/desktop-settings": {865 "packages/plugins/desktop-settings": {
866 "name": "@executor-js/plugin-desktop-settings",866 "name": "@executor-js/plugin-desktop-settings",
867 "version": "1.6.2",867 "version": "1.6.3",
868 "dependencies": {868 "dependencies": {
869 "@executor-js/sdk": "workspace:*",869 "@executor-js/sdk": "workspace:*",
870 "react": "catalog:",870 "react": "catalog:",
@@ -877,7 +877,7 @@ · 6 unmodified lines
877 },877 },
878 "packages/plugins/encrypted-secrets": {878 "packages/plugins/encrypted-secrets": {
879 "name": "@executor-js/plugin-encrypted-secrets",879 "name": "@executor-js/plugin-encrypted-secrets",
880 "version": "0.0.44",880 "version": "0.0.45",
881 "dependencies": {881 "dependencies": {
882 "@executor-js/sdk": "workspace:*",882 "@executor-js/sdk": "workspace:*",
883 "effect": "catalog:",883 "effect": "catalog:",
@@ -892,7 +892,7 @@ · 8 unmodified lines
892 },892 },
893 "packages/plugins/example": {893 "packages/plugins/example": {
894 "name": "@executor-js/plugin-example",894 "name": "@executor-js/plugin-example",
895 "version": "1.6.2",895 "version": "1.6.3",
896 "dependencies": {896 "dependencies": {
897 "@executor-js/sdk": "workspace:*",897 "@executor-js/sdk": "workspace:*",
898 },898 },
@@ -915,7 +915,7 @@ · 16 unmodified lines
915 },915 },
916 "packages/plugins/file-secrets": {916 "packages/plugins/file-secrets": {
917 "name": "@executor-js/plugin-file-secrets",917 "name": "@executor-js/plugin-file-secrets",
918 "version": "1.6.2",918 "version": "1.6.3",
919 "dependencies": {919 "dependencies": {
920 "@executor-js/sdk": "workspace:*",920 "@executor-js/sdk": "workspace:*",
921 },921 },
@@ -932,7 +932,7 @@ · 10 unmodified lines
932 },932 },
933 "packages/plugins/graphql": {933 "packages/plugins/graphql": {
934 "name": "@executor-js/plugin-graphql",934 "name": "@executor-js/plugin-graphql",
935 "version": "1.6.2",935 "version": "1.6.3",
936 "dependencies": {936 "dependencies": {
937 "@effect/platform-node": "catalog:",937 "@effect/platform-node": "catalog:",
938 "@executor-js/config": "workspace:*",938 "@executor-js/config": "workspace:*",
@@ -971,7 +971,7 @@ · 32 unmodified lines
971 },971 },
972 "packages/plugins/keychain": {972 "packages/plugins/keychain": {
973 "name": "@executor-js/plugin-keychain",973 "name": "@executor-js/plugin-keychain",
974 "version": "1.6.2",974 "version": "1.6.3",
975 "dependencies": {975 "dependencies": {
976 "@executor-js/sdk": "workspace:*",976 "@executor-js/sdk": "workspace:*",
977 "@napi-rs/keyring": "^1.2.0",977 "@napi-rs/keyring": "^1.2.0",
@@ -990,7 +990,7 @@ · 12 unmodified lines
990 },990 },
991 "packages/plugins/mcp": {991 "packages/plugins/mcp": {
992 "name": "@executor-js/plugin-mcp",992 "name": "@executor-js/plugin-mcp",
993 "version": "1.6.2",993 "version": "1.6.3",
994 "dependencies": {994 "dependencies": {
995 "@cfworker/json-schema": "^4.1.1",995 "@cfworker/json-schema": "^4.1.1",
996 "@effect/platform-node": "catalog:",996 "@effect/platform-node": "catalog:",
@@ -1034,7 +1034,7 @@ · 37 unmodified lines
1034 },1034 },
1035 "packages/plugins/onepassword": {1035 "packages/plugins/onepassword": {
1036 "name": "@executor-js/plugin-onepassword",1036 "name": "@executor-js/plugin-onepassword",
1037 "version": "1.6.2",1037 "version": "1.6.3",
1038 "dependencies": {1038 "dependencies": {
1039 "@1password/op-js": "^0.1.13",1039 "@1password/op-js": "^0.1.13",
1040 "@1password/sdk": "^0.4.1-beta.1",1040 "@1password/sdk": "^0.4.1-beta.1",
@@ -1068,7 +1068,7 @@ · 27 unmodified lines
1068 },1068 },
1069 "packages/plugins/openapi": {1069 "packages/plugins/openapi": {
1070 "name": "@executor-js/plugin-openapi",1070 "name": "@executor-js/plugin-openapi",
1071 "version": "1.6.2",1071 "version": "1.6.3",
1072 "dependencies": {1072 "dependencies": {
1073 "@effect/platform-node": "catalog:",1073 "@effect/platform-node": "catalog:",
1074 "@executor-js/config": "workspace:*",1074 "@executor-js/config": "workspace:*",
@@ -1109,7 +1109,7 @@ · 34 unmodified lines
1109 },1109 },
1110 "packages/plugins/provider-service-split": {1110 "packages/plugins/provider-service-split": {
1111 "name": "@executor-js/plugin-provider-service-split",1111 "name": "@executor-js/plugin-provider-service-split",
1112 "version": "0.0.16",1112 "version": "0.0.17",
1113 "dependencies": {1113 "dependencies": {
1114 "@executor-js/plugin-openapi": "workspace:*",1114 "@executor-js/plugin-openapi": "workspace:*",
1115 "@executor-js/sdk": "workspace:*",1115 "@executor-js/sdk": "workspace:*",
@@ -1126,7 +1126,7 @@ · 10 unmodified lines
1126 },1126 },
1127 "packages/plugins/toolkits": {1127 "packages/plugins/toolkits": {
1128 "name": "@executor-js/plugin-toolkits",1128 "name": "@executor-js/plugin-toolkits",
1129 "version": "1.5.37",1129 "version": "1.5.38",
1130 "dependencies": {1130 "dependencies": {
1131 "@executor-js/sdk": "workspace:*",1131 "@executor-js/sdk": "workspace:*",
1132 },1132 },
@@ -1195,7 +1195,7 @@ · 62 unmodified lines
1195 },1195 },
1196 "packages/react": {1196 "packages/react": {
1197 "name": "@executor-js/react",1197 "name": "@executor-js/react",
1198 "version": "1.4.65",1198 "version": "1.4.66",
1199 "dependencies": {1199 "dependencies": {
1200 "@base-ui/react": "^1.3.0",1200 "@base-ui/react": "^1.3.0",
1201 "@effect/atom-react": "catalog:",1201 "@effect/atom-react": "catalog:",
e2e/CHANGELOG.md+12−0
@@ -1,5 +1,17 @@
1# @executor-js/e2e1# @executor-js/e2e
2 2
3## 0.0.43
4
5### Patch Changes
6
7- Updated dependencies [[`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946), [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f), [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad), [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/plugin-mcp@1.6.3
9 - @executor-js/sdk@1.6.3
10 - @executor-js/plugin-openapi@1.6.3
11 - @executor-js/plugin-graphql@1.6.3
12 - @executor-js/plugin-toolkits@1.5.38
13 - @executor-js/api@1.4.66
14
3## 0.0.4215## 0.0.42
4 16
5### Patch Changes17### Patch Changes
e2e/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/e2e",2 "name": "@executor-js/e2e",
3 "version": "0.0.42",3 "version": "0.0.43",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "scripts": {6 "scripts": {
examples/all-plugins/CHANGELOG.md+14−0
@@ -1,5 +1,19 @@
1# @executor-js/example-all-plugins1# @executor-js/example-all-plugins
2 2
3## 0.0.64
4
5### Patch Changes
6
7- Updated dependencies [[`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946), [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f), [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad), [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/plugin-mcp@1.6.3
9 - @executor-js/sdk@1.6.3
10 - @executor-js/plugin-openapi@1.6.3
11 - @executor-js/plugin-graphql@1.6.3
12 - @executor-js/plugin-onepassword@1.6.3
13 - @executor-js/plugin-workos-vault@0.0.2
14 - @executor-js/plugin-file-secrets@1.6.3
15 - @executor-js/plugin-keychain@1.6.3
16
3## 0.0.6317## 0.0.63
4 18
5### Patch Changes19### Patch Changes
examples/all-plugins/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/example-all-plugins",2 "name": "@executor-js/example-all-plugins",
3 "version": "0.0.63",3 "version": "0.0.64",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "scripts": {6 "scripts": {
examples/docs-sdk-quickstart/CHANGELOG.md+8−0
@@ -1,5 +1,13 @@
1# @executor-js/example-docs-sdk-quickstart1# @executor-js/example-docs-sdk-quickstart
2 2
3## 0.0.49
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/plugin-openapi@1.6.3
10
3## 0.0.4811## 0.0.48
4 12
5### Patch Changes13### Patch Changes
examples/docs-sdk-quickstart/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/example-docs-sdk-quickstart",2 "name": "@executor-js/example-docs-sdk-quickstart",
3 "version": "0.0.48",3 "version": "0.0.49",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "scripts": {6 "scripts": {
packages/core/analytics/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/analytics1# @executor-js/analytics
2 2
3## 0.1.10
4
5### Patch Changes
6
7- Updated dependencies []:
8 - @executor-js/execution@1.6.3
9
3## 0.1.910## 0.1.9
4 11
5### Patch Changes12### Patch Changes
packages/core/analytics/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/analytics",2 "name": "@executor-js/analytics",
3 "version": "0.1.9",3 "version": "0.1.10",
4 "private": true,4 "private": true,
5 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/analytics",5 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/analytics",
6 "bugs": {6 "bugs": {
packages/core/api/CHANGELOG.md+9−0
@@ -1,5 +1,14 @@
1# @executor-js/api1# @executor-js/api
2 2
3## 1.4.66
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/execution@1.6.3
10 - @executor-js/host-mcp@1.4.4
11
3## 1.4.6512## 1.4.65
4 13
5### Patch Changes14### Patch Changes
packages/core/api/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/api",2 "name": "@executor-js/api",
3 "version": "1.4.65",3 "version": "1.4.66",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/core/cli/CHANGELOG.md+8−0
@@ -1,5 +1,13 @@
1# @executor-js/cli1# @executor-js/cli
2 2
3## 0.2.53
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/fumadb@1.5.8
10
3## 0.2.5211## 0.2.52
4 12
5### Patch Changes13### Patch Changes
packages/core/cli/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/cli",2 "name": "@executor-js/cli",
3 "version": "0.2.52",3 "version": "0.2.53",
4 "description": "CLI for the executor SDK — schema generation, migrations",4 "description": "CLI for the executor SDK — schema generation, migrations",
5 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/cli",5 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/cli",
6 "bugs": {6 "bugs": {
packages/core/config/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/config1# @executor-js/config
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/core/config/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/config",2 "name": "@executor-js/config",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/config",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/config",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/core/execution/CHANGELOG.md+8−0
@@ -1,5 +1,13 @@
1# @executor-js/execution1# @executor-js/execution
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/codemode-core@1.6.3
10
3## 1.6.211## 1.6.2
4 12
5### Patch Changes13### Patch Changes
packages/core/execution/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/execution",2 "name": "@executor-js/execution",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/execution",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/execution",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/core/fumadb/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# fumadb1# fumadb
2 2
3## 1.5.8
4
5### Patch Changes
6
7- [#1098](https://github.com/UsefulSoftwareCo/executor/pull/1098) [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae) Thanks [@aryasaatvik](https://github.com/aryasaatvik)! - Add a FumaDB bulk upsert query path and route plugin-storage bulk writes through
8 it so existing rows are updated without delete/reinsert churn.
9
3## 1.5.710## 1.5.7
4 11
5### Patch Changes12### Patch Changes
packages/core/fumadb/package.json+1−1
@@ -1,7 +1,7 @@
1{1{
2 "name": "@executor-js/fumadb",2 "name": "@executor-js/fumadb",
3 "description": "A library for interacting with different databases for your package.",3 "description": "A library for interacting with different databases for your package.",
4 "version": "1.5.7",4 "version": "1.5.8",
5 "repository": {5 "repository": {
6 "type": "git",6 "type": "git",
7 "url": "git+https://github.com/UsefulSoftwareCo/executor.git",7 "url": "git+https://github.com/UsefulSoftwareCo/executor.git",
packages/core/sdk/CHANGELOG.md+19−0
@@ -1,5 +1,24 @@
1# @executor-js/sdk1# @executor-js/sdk
2 2
3## 1.6.3
4
5### Patch Changes
6
7- [#1537](https://github.com/UsefulSoftwareCo/executor/pull/1537) [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060) Thanks [@Rish-it](https://github.com/Rish-it)! - Share the OAuth refresh gate across execution stacks so a rotating refresh token is redeemed once.
8
9 The in-flight refresh gate was built inside `createExecutor`, so it only covered one execution stack. A host builds a fresh stack per MCP session, and now per request, so two sessions resolving the same connection each read the same stored refresh token and each believed they were the refresh winner. Against a provider that rotates refresh tokens, the loser redeems a token the winner already spent, and a provider that detects reuse revokes the whole token family: the connection dies and the user has to reauthorize. The first refresh always succeeds, so the fault stayed invisible until a later expiry.
10
11 The gate now hangs off the root database handle, which is the object hosts already share across sessions and requests, so every stack over one handle converges on one gate. Its key includes the tenant, because a gate that spans tenants would otherwise let two tenants collide on one entry.
12
13 The grant also runs on its own detached fiber that callers await, rather than on whichever caller registered it. Sharing an entry across stacks would otherwise share the first caller's cancellation: a disconnected MCP client or an execution deadline would fail every peer waiting on that entry, and would abandon a refresh token the authorization server had already rotated, which is itself a dead connection. A cancelled peer now detaches without touching the grant, and a grant nobody is left waiting on still settles and still persists the rotated token.
14
15 Deduplication covers one database handle in one process. A host that builds a fresh handle per request or per session, and any multi-instance or multi-replica deployment, is out of scope here and still needs database-backed coordination, such as a compare-and-swap on the stored refresh token.
16
17- [#1098](https://github.com/UsefulSoftwareCo/executor/pull/1098) [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae) Thanks [@aryasaatvik](https://github.com/aryasaatvik)! - Add a FumaDB bulk upsert query path and route plugin-storage bulk writes through
18 it so existing rows are updated without delete/reinsert churn.
19- Updated dependencies [[`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
20 - @executor-js/fumadb@1.5.8
21
3## 1.6.222## 1.6.2
4 23
5## 1.6.124## 1.6.1
packages/core/sdk/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/sdk",2 "name": "@executor-js/sdk",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/sdk",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/sdk",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/core/vite-plugin/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/vite-plugin1# @executor-js/vite-plugin
2 2
3## 0.0.63
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 0.0.6210## 0.0.62
4 11
5### Patch Changes12### Patch Changes
packages/core/vite-plugin/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/vite-plugin",2 "name": "@executor-js/vite-plugin",
3 "version": "0.0.62",3 "version": "0.0.63",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/vite-plugin",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/core/vite-plugin",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/hosts/cloudflare/CHANGELOG.md+10−0
@@ -1,5 +1,15 @@
1# @executor-js/cloudflare1# @executor-js/cloudflare
2 2
3## 0.0.45
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/api@1.4.66
10 - @executor-js/execution@1.6.3
11 - @executor-js/host-mcp@1.4.4
12
3## 0.0.4413## 0.0.44
4 14
5### Patch Changes15### Patch Changes
packages/hosts/cloudflare/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/cloudflare",2 "name": "@executor-js/cloudflare",
3 "version": "0.0.44",3 "version": "0.0.45",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/hosts/mcp-apps-shell/CHANGELOG.md+8−0
@@ -1,5 +1,13 @@
1# @executor-js/mcp-apps-shell1# @executor-js/mcp-apps-shell
2 2
3## 1.4.14
4
5### Patch Changes
6
7- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546)]:
8 - @executor-js/react@1.4.66
9 - @executor-js/runtime-quickjs@1.6.3
10
3## 1.4.1311## 1.4.13
4 12
5### Patch Changes13### Patch Changes
packages/hosts/mcp-apps-shell/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/mcp-apps-shell",2 "name": "@executor-js/mcp-apps-shell",
3 "version": "1.4.13",3 "version": "1.4.14",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/kernel/core/CHANGELOG.md+2−0
@@ -1,5 +1,7 @@
1# @executor-js/codemode-core1# @executor-js/codemode-core
2 2
3## 1.6.3
4
3## 1.6.25## 1.6.2
4 6
5## 1.6.17## 1.6.1
packages/kernel/core/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/codemode-core",2 "name": "@executor-js/codemode-core",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/kernel/core",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/kernel/core",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/kernel/runtime-quickjs/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/runtime-quickjs1# @executor-js/runtime-quickjs
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies []:
8 - @executor-js/codemode-core@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/kernel/runtime-quickjs/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/runtime-quickjs",2 "name": "@executor-js/runtime-quickjs",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/kernel/runtime-quickjs",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/kernel/runtime-quickjs",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/kernel/runtime-workerd-subprocess/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/runtime-workerd-subprocess1# @executor-js/runtime-workerd-subprocess
2 2
3## 0.0.18
4
5### Patch Changes
6
7- Updated dependencies []:
8 - @executor-js/codemode-core@1.6.3
9
3## 0.0.1710## 0.0.17
4 11
5### Patch Changes12### Patch Changes
packages/kernel/runtime-workerd-subprocess/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/runtime-workerd-subprocess",2 "name": "@executor-js/runtime-workerd-subprocess",
3 "version": "0.0.17",3 "version": "0.0.18",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/plugins/desktop-settings/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/plugin-desktop-settings1# @executor-js/plugin-desktop-settings
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/plugins/desktop-settings/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-desktop-settings",2 "name": "@executor-js/plugin-desktop-settings",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/desktop-settings",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/desktop-settings",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/encrypted-secrets/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/plugin-encrypted-secrets1# @executor-js/plugin-encrypted-secrets
2 2
3## 0.0.45
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 0.0.4410## 0.0.44
4 11
5### Patch Changes12### Patch Changes
packages/plugins/encrypted-secrets/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-encrypted-secrets",2 "name": "@executor-js/plugin-encrypted-secrets",
3 "version": "0.0.44",3 "version": "0.0.45",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/plugins/example/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/plugin-example1# @executor-js/plugin-example
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/plugins/example/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-example",2 "name": "@executor-js/plugin-example",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/example",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/example",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/file-secrets/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/plugin-file-secrets1# @executor-js/plugin-file-secrets
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/plugins/file-secrets/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-file-secrets",2 "name": "@executor-js/plugin-file-secrets",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/file-secrets",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/file-secrets",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/graphql/CHANGELOG.md+10−0
@@ -1,5 +1,15 @@
1# @executor-js/plugin-graphql1# @executor-js/plugin-graphql
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/react@1.4.66
9 - @executor-js/sdk@1.6.3
10 - @executor-js/api@1.4.66
11 - @executor-js/config@1.6.3
12
3## 1.6.213## 1.6.2
4 14
5### Patch Changes15### Patch Changes
packages/plugins/graphql/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-graphql",2 "name": "@executor-js/plugin-graphql",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/graphql",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/graphql",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/keychain/CHANGELOG.md+7−0
@@ -1,5 +1,12 @@
1# @executor-js/plugin-keychain1# @executor-js/plugin-keychain
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9
3## 1.6.210## 1.6.2
4 11
5### Patch Changes12### Patch Changes
packages/plugins/keychain/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-keychain",2 "name": "@executor-js/plugin-keychain",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/keychain",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/keychain",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/mcp/CHANGELOG.md+36−0
@@ -1,5 +1,41 @@
1# @executor-js/plugin-mcp1# @executor-js/plugin-mcp
2 2
3## 1.6.3
4
5### Patch Changes
6
7- [#1815](https://github.com/UsefulSoftwareCo/executor/pull/1815) [`4b0fbf6`](https://github.com/UsefulSoftwareCo/executor/commit/4b0fbf68550516af9235c9267f91a962da993946) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **The add-MCP form stops dialling the server URL while it is still being typed**
8
9 The Server URL field auto-probes the endpoint after a 400ms pause. The only condition on that probe was that the trimmed value was non-empty, so every pause in typing dialled whatever was in the field: "h", "http://", the "a" in "http://a". Each of those probes failed, and the field dropped into a loading state and then an error with a retry button, for a value the user never meant to submit.
10
11 The probe now runs only when the value looks like a finished endpoint: it parses as a URL, its scheme is http or https, and its hostname is either a local development host or has a dot with a label on each side. The debounce is unchanged, so a completed URL is still probed without the user having to submit.
12
13 A probe that is superseded is also no longer allowed to answer. The field could previously report the outcome of a request for a URL that had since been edited, because each probe dispatched its result unconditionally. Editing the URL now invalidates any probe already in flight, and its reply is discarded rather than applied to the current value.
14
15- [#1702](https://github.com/UsefulSoftwareCo/executor/pull/1702) [`ba62f1a`](https://github.com/UsefulSoftwareCo/executor/commit/ba62f1a5d14b7002ba0a4686a9e1ae43bd77f54f) Thanks [@altaywtf](https://github.com/altaywtf)! - Allow MCP integrations to declare a catalog family and group any family with multiple services in the integrations UI.
16
17- [#1595](https://github.com/UsefulSoftwareCo/executor/pull/1595) [`8324e1e`](https://github.com/UsefulSoftwareCo/executor/commit/8324e1eb8b03965050147309f049bdb52be6fcad) Thanks [@GeiserX](https://github.com/GeiserX)! - **Stdio MCP servers no longer inherit executor's full environment**
18
19 A stdio MCP server that declared any `env` at all was spawned with every environment variable this process holds. The MCP SDK already guards against that: it spawns with `{ ...getDefaultEnvironment(), ...serverParams.env }`, where `getDefaultEnvironment()` is a sudo-style safe-list of `HOME`, `LOGNAME`, `PATH`, `SHELL`, `TERM` and `USER`. Passing `{ ...process.env, ...config.env }` did not add to that safe-list, it overwrote it. In practice, adding one third-party `npx` server went from "this server can see the API key I gave it" to "this server also holds `EXECUTOR_SECRET_KEY`, the key that decrypts every other stored credential, plus `EXECUTOR_AUTH_TOKEN` and `DATABASE_URL`". The leak sat on the `config.env` branch — the branch a credential-bearing integration takes.
20
21 A stdio server now receives the SDK's safe-list, the variables declared on the source config, and one short allowlist of infrastructure variables read from the host: `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY` (both spellings), `NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE` and `SSL_CERT_DIR`. Those carry no credential, no source config declares them, and a server behind a corporate proxy or an intercepting CA cannot reach anything without them — the same reasoning and the same list `service install` already uses when it bakes a supervised unit's minimal environment. The declared `env` wins on a key collision. On Windows that collision is resolved case-insensitively, because the OS treats `Path` and `PATH` as one variable while a JavaScript spread does not: a declared `http_proxy` now replaces an inherited `HTTP_PROXY` instead of travelling beside it, which would have left the child reading whichever spelling Windows resolved first.
22
23 If a stdio server relied on some other variable arriving from the host, set it explicitly on the source's `env`. That is now the only way anything beyond the lists above reaches a server, and it is the mechanism that already existed for it.
24
25- [#1813](https://github.com/UsefulSoftwareCo/executor/pull/1813) [`6305b6d`](https://github.com/UsefulSoftwareCo/executor/commit/6305b6d11505358fa73ec2b3e768ec4256c36435) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **An MCP tool's reserved `_meta` map survives `tools/list` decoding and reaches the persisted catalog**
26
27 The MCP spec reserves `_meta` on `Tool` for implementation-defined data, and servers use it for host-only routing and policy hints that do not belong in the closed `annotations` set. The plugin decoded each listed tool with a closed struct that did not declare the field, so `_meta` was discarded before the manifest entry was built. A host that embeds the plugin as its MCP client had no way to recover it: no hook exposes the raw `tools/list` result, and `connections.refresh()` answers with already-built tools.
28
29 The listed-tool decode now declares `_meta`, and the manifest entry carries it through. Executor's own `Tool` has no `_meta` field, so `toToolDef` stamps the map into the `mcp` envelope the plugin already persists in each tool row's annotations, next to the real MCP tool name. The stamp schema declares it too, so it is not stripped a second time when a row is read back at invoke time. A host reads it from `annotations.mcp._meta`.
30
31 The map stays opaque. Nothing in the plugin interprets its contents, and it is never merged into anything the model sees. Because it is entirely server-controlled, it is decoded permissively: a `_meta` that is not the spec's map shape is ignored for that tool rather than failing the whole-list decode, which would otherwise drop every tool the server advertises.
32
33- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
34 - @executor-js/react@1.4.66
35 - @executor-js/sdk@1.6.3
36 - @executor-js/api@1.4.66
37 - @executor-js/config@1.6.3
38
3## 1.6.239## 1.6.2
4 40
5### Patch Changes41### Patch Changes
packages/plugins/mcp/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-mcp",2 "name": "@executor-js/plugin-mcp",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/mcp",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/mcp",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/onepassword/CHANGELOG.md+9−0
@@ -1,5 +1,14 @@
1# @executor-js/plugin-onepassword1# @executor-js/plugin-onepassword
2 2
3## 1.6.3
4
5### Patch Changes
6
7- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/react@1.4.66
9 - @executor-js/sdk@1.6.3
10 - @executor-js/api@1.4.66
11
3## 1.6.212## 1.6.2
4 13
5### Patch Changes14### Patch Changes
packages/plugins/onepassword/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-onepassword",2 "name": "@executor-js/plugin-onepassword",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/onepassword",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/onepassword",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/openapi/CHANGELOG.md+18−0
@@ -1,5 +1,23 @@
1# @executor-js/plugin-openapi1# @executor-js/plugin-openapi
2 2
3## 1.6.3
4
5### Patch Changes
6
7- [#1530](https://github.com/UsefulSoftwareCo/executor/pull/1530) [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626) Thanks [@BittuBarnwal7479](https://github.com/BittuBarnwal7479)! - Multipart file fields in an OpenAPI spec now accept and send real files. A `multipart/form-data` property typed as a binary or byte string is rewritten into the SDK's tool-file schema when the tool is extracted, so an agent supplies a file the same way it does everywhere else. On invocation those values are decoded back into `File`/`Blob` parts — as bare properties and inside arrays, with a per-property `encoding.contentType` applied to each file part — instead of being JSON-stringified into the form body, which is what upstreams were previously rejecting. A file whose base64 payload does not decode now fails the invocation and names the field, rather than sending the file envelope as JSON.
8
9 The rewrite advertises only the shapes the request encoder can deliver. Two are deliberately left alone:
10 - A binary field nested inside an object property. Only top-level multipart properties and direct items of a top-level array property become form parts.
11 - A multipart body schema, or one of its properties, behind a `$ref`. Component schemas are carried through unresolved by design — the streaming compile path never materializes `components.schemas` — so a `$ref`'d file field keeps its declared binary string type.
12
13 The rewrite reads the request schema's own `properties` map rather than walking every object key, so a `default`, `example`, or vendor extension that happens to look like a binary string schema is untouched. Descriptions, titles, and nullability on the replaced field are carried onto the file schema.
14
15- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
16 - @executor-js/react@1.4.66
17 - @executor-js/sdk@1.6.3
18 - @executor-js/api@1.4.66
19 - @executor-js/config@1.6.3
20
3## 1.6.221## 1.6.2
4 22
5### Patch Changes23### Patch Changes
packages/plugins/openapi/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-openapi",2 "name": "@executor-js/plugin-openapi",
3 "version": "1.6.2",3 "version": "1.6.3",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/openapi",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/openapi",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/plugins/provider-service-split/CHANGELOG.md+8−0
@@ -1,5 +1,13 @@
1# @executor-js/plugin-provider-service-split1# @executor-js/plugin-provider-service-split
2 2
3## 0.0.17
4
5### Patch Changes
6
7- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`85b1955`](https://github.com/UsefulSoftwareCo/executor/commit/85b1955b4d24c332e637e15a025d64455e28a626), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/sdk@1.6.3
9 - @executor-js/plugin-openapi@1.6.3
10
3## 0.0.1611## 0.0.16
4 12
5### Patch Changes13### Patch Changes
packages/plugins/provider-service-split/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-provider-service-split",2 "name": "@executor-js/plugin-provider-service-split",
3 "version": "0.0.16",3 "version": "0.0.17",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {
packages/plugins/toolkits/CHANGELOG.md+9−0
@@ -1,5 +1,14 @@
1# @executor-js/plugin-toolkits1# @executor-js/plugin-toolkits
2 2
3## 1.5.38
4
5### Patch Changes
6
7- Updated dependencies [[`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce), [`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
8 - @executor-js/react@1.4.66
9 - @executor-js/sdk@1.6.3
10 - @executor-js/api@1.4.66
11
3## 1.5.3712## 1.5.37
4 13
5### Patch Changes14### Patch Changes
packages/plugins/toolkits/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/plugin-toolkits",2 "name": "@executor-js/plugin-toolkits",
3 "version": "1.5.37",3 "version": "1.5.38",
4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/toolkits",4 "homepage": "https://github.com/UsefulSoftwareCo/executor/tree/main/packages/plugins/toolkits",
5 "bugs": {5 "bugs": {
6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"6 "url": "https://github.com/UsefulSoftwareCo/executor/issues"
packages/react/CHANGELOG.md+28−0
@@ -1,5 +1,33 @@
1# @executor-js/react1# @executor-js/react
2 2
3## 1.4.66
4
5### Patch Changes
6
7- [#1814](https://github.com/UsefulSoftwareCo/executor/pull/1814) [`66fb1a4`](https://github.com/UsefulSoftwareCo/executor/commit/66fb1a4154226d28691ca83bdf6f3daa417ef0ce) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **A click outside a dialog or sheet no longer discards the form inside it**
8
9 Radix dismisses an overlay surface on any un-prevented outside interaction, and `DialogContent` and `SheetContent` only prevented that for clicks landing in a portaled combobox or select popup. Every other outside click fell through to dismissal, so a stray click on the page behind a form — after switching windows to copy an ID, for example — closed the surface and destroyed what the user had typed. These surfaces unmount their state on close by design, so nothing was recoverable.
10
11 The default is now the opposite: an outside interaction keeps the surface open. Escape and the close button are unchanged and still close it. `DialogContent` and `SheetContent` take a new `dismissOnOutsideClick` prop for surfaces with nothing to lose — confirmations, pickers, and read-only panels — and the portaled-popup guard still applies there, so choosing a combobox option never dismisses.
12
13 `CommandDialog` sets `dismissOnOutsideClick` on by default, because a command palette holds only a search string and clicking away is the expected way to leave it.
14
15- [#1822](https://github.com/UsefulSoftwareCo/executor/pull/1822) [`d7e4b73`](https://github.com/UsefulSoftwareCo/executor/commit/d7e4b73a86b8e413af70e0fcb26f38a35a3f4546) Thanks [@RhysSullivan](https://github.com/RhysSullivan)! - **An OAuth app can now be registered without an RFC 8707 resource, and that absence holds on every request**
16
17 Microsoft Entra v2 rejects any authorization request that carries both a v2 `scope` (such as `https://api.fabric.microsoft.com/.default`) and the RFC 8707 `resource` parameter, failing with `AADSTS9010010` before the consent screen. Executor made that unavoidable for MCP servers behind Entra: registering an app for an MCP integration always derived the MCP endpoint as the resource, the form had no field to change it, and so every request carried the parameter Entra rejects.
18
19 The register/edit OAuth app form now shows the resource indicator. It is still prefilled for MCP servers — nothing changes for providers that accept the parameter — but it can be cleared, and a cleared value persists as "no resource". A resource-less app then omits `resource` on all four grants alike: the authorization request, the code exchange, token refresh, and client-credentials. Symmetry matters here — sending `resource` on authorize but not on the token request (or the reverse) would bind the two tokens to different audiences.
20
21 Two adjacent gaps closed with it:
22 - MCP scope discovery no longer depends on the app's resource. It now falls back to the integration's own discovery URL (the MCP endpoint), so clearing the resource does not break connecting.
23 - Token refresh for a first-party OAuth app dropped the app's configured resource, refreshing to a different audience than the original grant. It now sends the same resource the authorization request sent.
24
25 Apps that keep their resource — the default for every discovered MCP server — behave exactly as before: the parameter is sent on every grant, as the MCP authorization spec expects.
26
27- Updated dependencies [[`c1f51b7`](https://github.com/UsefulSoftwareCo/executor/commit/c1f51b7f96328b795669bb3d241667660dc2b060), [`02b52cd`](https://github.com/UsefulSoftwareCo/executor/commit/02b52cd01b09d3601ffe88d1f9c0b777f26e76ae)]:
28 - @executor-js/sdk@1.6.3
29 - @executor-js/api@1.4.66
30
3## 1.4.6531## 1.4.65
4 32
5### Patch Changes33### Patch Changes
packages/react/package.json+1−1
@@ -1,6 +1,6 @@
1{1{
2 "name": "@executor-js/react",2 "name": "@executor-js/react",
3 "version": "1.4.65",3 "version": "1.4.66",
4 "private": true,4 "private": true,
5 "type": "module",5 "type": "module",
6 "exports": {6 "exports": {