diff --git a/.copilot-schema-version b/.copilot-schema-version index a528c8a..0c161af 100644 --- a/.copilot-schema-version +++ b/.copilot-schema-version @@ -1 +1 @@ -1.0.81-5 +1.0.81-6 diff --git a/.github/skills/update-upstream/SKILL.md b/.github/skills/update-upstream/SKILL.md index dce58fc..9ede113 100644 --- a/.github/skills/update-upstream/SKILL.md +++ b/.github/skills/update-upstream/SKILL.md @@ -141,9 +141,14 @@ without copying temporary audit notes into evergreen docs. Add a concise Use the smallest targeted gates during iteration, then run: ```bash +COPILOT_UPSTREAM_VALIDATION=true bb test bb ci:full ``` +The first command validates committed exact-pin evidence against the resolved +local upstream checkout. Normal `bb test` and CI remain hermetic when that +external checkout is unavailable. + If authenticated end-to-end prerequisites are unavailable, run `bb ci` and state the limitation. Review example output, generated diffs, and the machine-readable parity inventory. diff --git a/CHANGELOG.md b/CHANGELOG.md index ef130e6..46a6606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,9 +28,9 @@ All notable changes to this project will be documented in this file. This change [upstream PR #2364](https://github.com/github/copilot-sdk/pull/2364)) ### Changed (post-v1.0.12-preview.0 sync) -- Updated the runtime schema pin from `1.0.80` to `1.0.81-5` and recertified +- Updated the runtime schema pin from `1.0.80` to `1.0.81-6` and recertified the complete stable Node SDK public surface through upstream commit - [`ea41dadb199725766d5097f4592c17be3200035f`](https://github.com/github/copilot-sdk/commit/ea41dadb199725766d5097f4592c17be3200035f). + [`cc0438d66e3e68c333537cb935d9425d4e4ed8d5`](https://github.com/github/copilot-sdk/commit/cc0438d66e3e68c333537cb935d9425d4e4ed8d5). Experimental assisted-approval controls, ephemeral UI queries, factory lifecycle events, generated-only RPC declarations, and Node-specific package resolution remain intentionally excluded. @@ -40,16 +40,20 @@ All notable changes to this project will be documented in this file. This change `:assisted-approval-model`. This replaces the removed aggregate allow-all booleans and `"off"` / `"auto"` / `"on"` mode fields. - `resume-session`, `resume-session :large-output map Tool output handling config. Forwarded on session.resume as the official SDK’s largeOutput field. -

When :mcp-servers is present, the SDK first resumes the session and then calls session.mcp.reloadWithConfig with the same converted server configuration. This applies to blocking and async resume, and therefore to join-session. Reload errors propagate, and the partially registered local session is removed; the SDK does not silently fall back for older runtimes. Reload requests use a bounded timeout of at least 60 seconds, extended to the largest configured :mcp-timeout plus a five-second transport margin.

+

When :mcp-servers is present, the SDK sends the converted server configuration as mcpServers in the session.resume request. This applies to blocking and async resume, and therefore to join-session. Omitting the key omits mcpServers; an empty map sends an empty configuration.

When :on-permission-request is set to default-join-session-permission-handler, the SDK sends requestPermission: false on the wire, telling the CLI that this client does not handle permission requests. Any other handler sends requestPermission: true.

;; Resume with a different model and reasoning effort
 (copilot/resume-session client "session-123"
diff --git a/doc/api/github.copilot-sdk.client.html b/doc/api/github.copilot-sdk.client.html
index a808b66..03624ce 100644
--- a/doc/api/github.copilot-sdk.client.html
+++ b/doc/api/github.copilot-sdk.client.html
@@ -87,7 +87,7 @@
 

ping

(ping client)(ping client message)

Ping the server to check connectivity. Returns {:message :timestamp :protocol-version}.

:timestamp is either an ISO 8601 date-time string (e.g. “2026-05-21T08:00:00Z”; CLI ≥ 1.0.51, upstream PR #1340) or a numeric epoch-millis value, depending on the CLI version; the SDK forwards whatever the server sends.

resume-session

(resume-session client session-id config)

Resume an existing session by ID.

-

Config options (:on-permission-request is optional since upstream PR #1308 — omit it to leave permission requests pending for manual resolution via copilot/handle-pending-permission-request!): - :on-permission-request - Permission handler function (optional, e.g. approve-all). When omitted, permission requests are surfaced as :copilot/permission.requested events and remain pending until resolved by the application. - :client-name - Client name to identify the application (included in User-Agent header) - :model - Change the model for the resumed session - :tools - Tools exposed to the CLI server - :system-message - System message configuration {:mode :content} - :available-tools - List of tool names to allow - :excluded-tools - List of tool names to disable - :tool-search - Tool discovery config {:enabled :defer-threshold} - :provider - Custom provider configuration (BYOK) - :streaming? - Enable streaming responses - :mcp-servers - MCP server configurations. When present, resume applies the same config with session.mcp.reloadWithConfig after session.resume; reload failures fail the resume and clean up the local session. - :custom-agents - Custom agent configurations - :default-agent - Built-in agent config, e.g. {:excluded-tools “private_tool”} - :config-directory - Override configuration directory. :config-dir remains a deprecated alias. - :skill-directories - Directories to load skills from - :disabled-skills - Skills to disable - :infinite-sessions - Infinite session configuration - :memory - Persistent memory config {:enabled boolean} (upstream PR #1617). Parity with create-session; omitted when unset. - :reasoning-effort - Reasoning effort level: “low”, “medium”, “high”, or “xhigh” - :github-token - GitHub token for this session (sent as gitHubToken) - :on-user-input-request - Handler for ask_user requests - :on-elicitation-request - Handler for elicitation requests (upstream PRs #908, #960). Single-arg handler receives an ElicitationContext map with :session-id, :message, :requested-schema, :mode, :elicitation-source, :url. Returns an ElicitationResult map; omit :content for decline/cancel results. - :on-mcp-auth-request - Handler for interactive MCP OAuth requests (upstream PR #1669). Same shape as create-session. On resume, interest in mcp.oauth_required is registered before the resume RPC so OAuth needed while the runtime replays state reaches the handler. - :hooks - Lifecycle hooks map - :on-event - Event handler (1-arg fn) registered before the RPC call. Guarantees early events like session.start are not missed. - :enable-config-discovery - Boolean. Auto-discover .mcp.json, skills, etc. (upstream PR #1044) - :enable-mcp-apps - Boolean (@experimental). See create-session; explicit true sends requestMcpApps: true on resume, while false and omission send nothing. (https://github.com/github/copilot-sdk/pull/1335) - :model-capabilities - Model capabilities override map (upstream PR #1029). Same shape as create-session; :adaptive-thinking and :max-output-tokens are experimental CLI-protocol extras. - :include-sub-agent-streaming-events? - Boolean. When true (default), streaming events from sub-agents are forwarded to this session’s event stream. (upstream PR #1108) - :enable-session-telemetry? - Boolean. See create-session (upstream PR #1224). - :excluded-builtin-agents - Vector of strings. See create-session (upstream PR #1865). - :enable-citations - Boolean (@experimental). See create-session (upstream PR #1865). - :enable-file-change-tracking? - Boolean. See create-session. On resume, tracking can start only when the runtime still has a valid baseline; earlier untracked turns cannot be reconstructed. - :session-limits - Map (@experimental). See create-session (upstream PR #1865). - :enable-managed-settings? - Boolean. See create-session (upstream PR #1925). - :request-extensions? - Boolean. See create-session; explicit false is forwarded. - :extension-sdk-path - String path override for extension subprocesses. See create-session. - :extension-info - Stable extension identity {:source string :name string}. - :canvas-provider - Map {:id .. :name ..}. See create-session (upstream PR #1847). - :on-exit-plan-mode - Handler for exitPlanMode.request RPCs. See create-session (upstream PR #1228). - :on-auto-mode-switch - Handler for autoModeSwitch.request RPCs. See create-session (upstream PR #1228).

+

Config options (:on-permission-request is optional since upstream PR #1308 — omit it to leave permission requests pending for manual resolution via copilot/handle-pending-permission-request!): - :on-permission-request - Permission handler function (optional, e.g. approve-all). When omitted, permission requests are surfaced as :copilot/permission.requested events and remain pending until resolved by the application. - :client-name - Client name to identify the application (included in User-Agent header) - :model - Change the model for the resumed session - :tools - Tools exposed to the CLI server - :system-message - System message configuration {:mode :content} - :available-tools - List of tool names to allow - :excluded-tools - List of tool names to disable - :tool-search - Tool discovery config {:enabled :defer-threshold} - :provider - Custom provider configuration (BYOK) - :streaming? - Enable streaming responses - :mcp-servers - MCP server configurations, applied as part of session.resume. - :custom-agents - Custom agent configurations - :default-agent - Built-in agent config, e.g. {:excluded-tools “private_tool”} - :config-directory - Override configuration directory. :config-dir remains a deprecated alias. - :skill-directories - Directories to load skills from - :disabled-skills - Skills to disable - :infinite-sessions - Infinite session configuration - :memory - Persistent memory config {:enabled boolean} (upstream PR #1617). Parity with create-session; omitted when unset. - :reasoning-effort - Reasoning effort level: “low”, “medium”, “high”, or “xhigh” - :github-token - GitHub token for this session (sent as gitHubToken) - :on-user-input-request - Handler for ask_user requests - :on-elicitation-request - Handler for elicitation requests (upstream PRs #908, #960). Single-arg handler receives an ElicitationContext map with :session-id, :message, :requested-schema, :mode, :elicitation-source, :url. Returns an ElicitationResult map; omit :content for decline/cancel results. - :on-mcp-auth-request - Handler for interactive MCP OAuth requests (upstream PR #1669). Same shape as create-session. On resume, interest in mcp.oauth_required is registered before the resume RPC so OAuth needed while the runtime replays state reaches the handler. - :hooks - Lifecycle hooks map - :on-event - Event handler (1-arg fn) registered before the RPC call. Guarantees early events like session.start are not missed. - :enable-config-discovery - Boolean. Auto-discover .mcp.json, skills, etc. (upstream PR #1044) - :enable-mcp-apps - Boolean (@experimental). See create-session; explicit true sends requestMcpApps: true on resume, while false and omission send nothing. (https://github.com/github/copilot-sdk/pull/1335) - :model-capabilities - Model capabilities override map (upstream PR #1029). Same shape as create-session; :adaptive-thinking and :max-output-tokens are experimental CLI-protocol extras. - :include-sub-agent-streaming-events? - Boolean. When true (default), streaming events from sub-agents are forwarded to this session’s event stream. (upstream PR #1108) - :enable-session-telemetry? - Boolean. See create-session (upstream PR #1224). - :excluded-builtin-agents - Vector of strings. See create-session (upstream PR #1865). - :enable-citations - Boolean (@experimental). See create-session (upstream PR #1865). - :enable-file-change-tracking? - Boolean. See create-session. On resume, tracking can start only when the runtime still has a valid baseline; earlier untracked turns cannot be reconstructed. - :session-limits - Map (@experimental). See create-session (upstream PR #1865). - :enable-managed-settings? - Boolean. See create-session (upstream PR #1925). - :request-extensions? - Boolean. See create-session; explicit false is forwarded. - :extension-sdk-path - String path override for extension subprocesses. See create-session. - :extension-info - Stable extension identity {:source string :name string}. - :canvas-provider - Map {:id .. :name ..}. See create-session (upstream PR #1847). - :on-exit-plan-mode - Handler for exitPlanMode.request RPCs. See create-session (upstream PR #1228). - :on-auto-mode-switch - Handler for autoModeSwitch.request RPCs. See create-session (upstream PR #1228).

Returns a CopilotSession.

set-foreground-session-id!

(set-foreground-session-id! client session-id)

Set the foreground session (TUI+server mode). Requests the TUI to switch to displaying the specified session.

start!

(start! client)

Start the CLI server and establish connection. Blocks until connected or throws on error.

diff --git a/doc/api/github.copilot-sdk.html b/doc/api/github.copilot-sdk.html index 3e9e468..7abf337 100644 --- a/doc/api/github.copilot-sdk.html +++ b/doc/api/github.copilot-sdk.html @@ -296,7 +296,7 @@

telemetry is a map of string bucket names to JSON object maps.

resume-factory!

(resume-factory! session run-id)(resume-factory! session run-id options)

resume-session

(resume-session client session-id config)

Resume an existing session by ID. Accepts the same config options as create-session (except :session-id and :cloud), including the experimental :enable-mcp-apps host opt-in, plus: - :disable-resume? - When true, skip emitting the session.resume event (default: false)

:on-permission-request is optional (since upstream PR #1308) — omit it to leave permission requests pending for manual resolution.

-

When :mcp-servers is present, resume applies the same configuration with session.mcp.reloadWithConfig after session.resume. A reload failure fails the resume and cleans up the local session.

+

When :mcp-servers is present, the configuration is applied by session.resume.

Example:

(def session (copilot/resume-session client "session-123"
                {:on-permission-request copilot/approve-all}))
diff --git a/doc/api/overview.html b/doc/api/overview.html
index 5be7246..28432ee 100644
--- a/doc/api/overview.html
+++ b/doc/api/overview.html
@@ -118,9 +118,8 @@ 

Remote Serve :mcp-headers map No HTTP headers (e.g., for authentication) -

Resume-Time Reload

-

When :mcp-servers is supplied to resume-session or <resume-session, the SDK sends the configuration with session.resume and then applies the same converted map through session.mcp.reloadWithConfig. join-session inherits this behavior because it resumes the parent session internally.

-

The reload is part of the resume contract: an RPC error or closed response fails the operation and removes the partially registered local session. There is no silent fallback for runtimes that do not support the reload method. Omitting :mcp-servers sends neither a reload request nor an empty configuration.

+

Resume-Time Configuration

+

When :mcp-servers is supplied to resume-session or <resume-session, the SDK sends the converted configuration as mcpServers in the session.resume request. join-session inherits this behavior because it resumes the parent session internally. Omitting :mcp-servers omits the wire key; an empty map sends an empty configuration.

Disabling MCP Servers

Disable specific servers for a session without removing their :mcp-servers entry:

(copilot/with-client-session [session
diff --git a/doc/mcp/overview.md b/doc/mcp/overview.md
index 8615294..8a4ea1d 100644
--- a/doc/mcp/overview.md
+++ b/doc/mcp/overview.md
@@ -126,18 +126,13 @@ Here's a complete working example using the official [`@modelcontextprotocol/ser
 | `:mcp-defer-tools` | keyword | No | **Experimental, CLI-only:** tool-deferral policy `:auto` or `:never`. Wire-encoded as `deferTools` (upstream schema 1.0.63); this field is not exposed by the official Node SDK's `MCPServerConfig`. |
 | `:mcp-headers` | map | No | HTTP headers (e.g., for authentication) |
 
-### Resume-Time Reload
+### Resume-Time Configuration
 
 When `:mcp-servers` is supplied to `resume-session` or `wire mcp-servers)}})
-
-(def ^:private default-mcp-reload-timeout-ms 60000)
-(def ^:private mcp-reload-transport-margin-ms 5000)
-
-(defn- mcp-reload-timeout-ms
-  [mcp-servers]
-  (reduce
-   max
-   default-mcp-reload-timeout-ms
-   (keep (fn [{:keys [mcp-timeout]}]
-           (when mcp-timeout
-             (+ mcp-timeout mcp-reload-transport-margin-ms)))
-         (vals mcp-servers))))
-
 (defn- resume-session-result*
   [client session-id config]
   (validate-provider-config! config)
@@ -3038,12 +3020,6 @@
       (install-session-fs-handler! client session-id session config)
       (register-mcp-auth-interest! client session-id config)
       (let [result (proto/send-request! connection-io "session.resume" params)]
-        (when (contains? config :mcp-servers)
-          (proto/send-request!
-           connection-io
-           "session.mcp.reloadWithConfig"
-           (mcp-reload-with-config-params session-id (:mcp-servers config))
-           (mcp-reload-timeout-ms (:mcp-servers config))))
         (session/set-workspace-path! client session-id (:workspace-path result))
         (session/set-capabilities! client session-id (:capabilities result))
         (session/set-open-canvases! client session-id (:open-canvases result))
@@ -3077,9 +3053,7 @@
    - :tool-search        - Tool discovery config {:enabled :defer-threshold}
    - :provider           - Custom provider configuration (BYOK)
    - :streaming?         - Enable streaming responses
-   - :mcp-servers        - MCP server configurations. When present, resume applies the same
-                           config with session.mcp.reloadWithConfig after session.resume;
-                           reload failures fail the resume and clean up the local session.
+   - :mcp-servers        - MCP server configurations, applied as part of session.resume.
    - :custom-agents      - Custom agent configurations
    - :default-agent      - Built-in agent config, e.g. {:excluded-tools [\"private_tool\"]}
    - :config-directory   - Override configuration directory.
@@ -3340,41 +3314,14 @@
                     (session/remove-session! client session-id)
                     (ex-info (str "Failed to resume session: " (:message err))
                              {:error err :session-id session-id}))
-                (let [result (:result response)
-                      reload? (contains? config :mcp-servers)
-                      reload-response
-                      (when reload?
-                        ( report-resource io/resource slurp edn/read-string))
+
+(defn- resolve-upstream
+  []
+  (let [{:keys [exit out err]}
+        (sh/sh "bash"
+               ".github/skills/update-upstream/scripts/resolve-upstream.sh")]
+    (when-not (zero? exit)
+      (throw (ex-info "Could not resolve the upstream checkout"
+                      {:exit exit :stderr err})))
+    (str/trim out)))
+
+(def ^:private upstream-repo
+  (delay
+    (when upstream-validation-enabled?
+      (resolve-upstream))))
+
+(defn- git-lines
+  [upstream & args]
+  (let [{:keys [exit out err]}
+        (apply sh/sh (concat ["git" "-C" upstream] args))]
+    (when-not (zero? exit)
+      (throw (ex-info "Could not inspect the upstream checkout"
+                      {:args args :exit exit :stderr err})))
+    (->> (str/split-lines out)
+         (remove str/blank?)
+         vec)))
+
+(defn- sha256-file
+  [path]
+  (let [digest (MessageDigest/getInstance "SHA-256")
+        bytes (Files/readAllBytes (Paths/get path (make-array String 0)))]
+    (format "%064x" (BigInteger. 1 (.digest digest bytes)))))
+
+(defn- evidence-references
+  [report]
+  (set (concat
+        (mapcat :evidence (:ported-internal-deltas report))
+        (mapcat :evidence (:intentional-exclusions report)))))
+
+(deftest upstream-range-and-classification-are-exact
+  (let [{:keys [base target exact-commits classified-files]} (read-report)
+        expected-commits (mapv :sha exact-commits)
+        expected-files (mapcat :paths classified-files)]
+    (is (= "ea41dadb199725766d5097f4592c17be3200035f" base))
+    (is (= "cc0438d66e3e68c333537cb935d9425d4e4ed8d5" target))
+    (is (= ["21d738ea2cad2b49bb40b125046a29c0880f1504"
+            "cc0438d66e3e68c333537cb935d9425d4e4ed8d5"]
+           expected-commits))
+    (is (= 31 (count expected-files)))
+    (is (= (count expected-files) (count (distinct expected-files))))
+    (is (every? allowed-classifications
+                (map :classification classified-files)))
+    (when-let [upstream @upstream-repo]
+      (let [actual-commits (git-lines upstream "rev-list" "--reverse"
+                                      (str base ".." target))
+            actual-files (git-lines upstream "diff" "--name-only"
+                                    (str base ".." target))]
+        (is (= expected-commits actual-commits))
+        (is (= (set expected-files) (set actual-files)))
+        (is (= (count actual-files) (count (distinct actual-files))))))))
+
+(deftest public-surface-and-evidence-are-complete
+  (let [{:keys [target public-surface-audit ported-internal-deltas
+                source-evidence] :as report}
+        (read-report)
+        evidence-ids (set (keys source-evidence))]
+    (is (empty? (:stable-public-deltas public-surface-audit)))
+    (is (empty? (:unclassified-deltas public-surface-audit)))
+    (is (= #{:resume/mcp-config-in-resume-only}
+           (set (map :id ported-internal-deltas))))
+    (is (= evidence-ids (evidence-references report)))
+    (when-let [upstream @upstream-repo]
+      (doseq [[evidence-id {:keys [path symbol]}] source-evidence]
+        (testing (name evidence-id)
+          (let [{:keys [exit out]}
+                (sh/sh "git" "-C" upstream "grep" "-F"
+                       symbol target "--" path)]
+            (is (zero? exit))
+            (is (str/includes? out symbol))))))))
+
+(deftest current-runtime-schema-is-exact
+  (let [{:keys [schema version]} (read-report)
+        api-schema (json/read-str (slurp "schemas/api.schema.json"))
+        definitions (get api-schema "definitions")
+        account-login (get definitions "AccountLoginRequest")
+        permission-mode-source (get definitions "PermissionModeSource")
+        approve-all-source (get definitions "PermissionsSetApproveAllSource")]
+    (is (= (:runtime-pin schema)
+           (str/trim (slurp ".copilot-schema-version"))))
+    (is (= (get-in schema [:api :sha256])
+           (sha256-file "schemas/api.schema.json")))
+    (is (= (get-in schema [:session-events :sha256])
+           (sha256-file "schemas/session-events.schema.json")))
+    (is (= #{"host" "token"} (set (get account-login "required"))))
+    (is (contains? (get account-login "properties") "login"))
+    (is (= false (get account-login "additionalProperties")))
+    (is (= "experimental" (get permission-mode-source "stability")))
+    (is (contains? (set (get permission-mode-source "enum"))
+                   "user_setting"))
+    (is (contains? (set (get approve-all-source "enum"))
+                   "user_setting"))
+    (is (= {:sdk "1.0.11.0"
+            :changed? false
+            :release-required? false}
+           version))))
diff --git a/test/github/copilot_sdk/integration/stable_sync_ea41d_test.clj b/test/github/copilot_sdk/integration/stable_sync_ea41d_test.clj
index cb3a761..5ffad04 100644
--- a/test/github/copilot_sdk/integration/stable_sync_ea41d_test.clj
+++ b/test/github/copilot_sdk/integration/stable_sync_ea41d_test.clj
@@ -8,20 +8,11 @@
             [clojure.test :refer [deftest is testing]]
             [github.copilot-sdk :as sdk]
             [github.copilot-sdk.generated.event-specs :as generated-events]
-            [github.copilot-sdk.specs])
-  (:import [java.nio.file Files Paths]
-           [java.security MessageDigest]))
+            [github.copilot-sdk.specs]))
 
 (def ^:private stable-delta-resource
   "resources/stable_upstream_delta_ea41d.edn")
 
-(defn- sha256
-  [path]
-  (let [digest (.digest (MessageDigest/getInstance "SHA-256")
-                        (Files/readAllBytes
-                         (Paths/get path (make-array String 0))))]
-    (apply str (map #(format "%02x" (bit-and % 0xff)) digest))))
-
 (defn- read-schema
   [path]
   (with-open [reader (io/reader path)]
@@ -59,11 +50,6 @@
                "session-events.schema.json"
                "9fd414f5020c317a234da6d7a06a4d0ef02ddad227ddc9962dced49302e5e8ec"}
                (get-in report [:upstream :schema-sha256])))
-        (is (= (get-in report [:upstream :schema-sha256])
-               {"api.schema.json" (sha256 "schemas/api.schema.json")
-               "session-events.schema.json"
-               (sha256 "schemas/session-events.schema.json")}))
-        (is (= "1.0.81-5\n" (slurp ".copilot-schema-version")))
         (is (= (:stable-delta-ids report)
                (set (map :id stable-deltas))))
         (is (empty? (:unclassified-stable report)))
diff --git a/test/github/copilot_sdk/integration/tools_config_test.clj b/test/github/copilot_sdk/integration/tools_config_test.clj
index f5db164..317db2f 100644
--- a/test/github/copilot_sdk/integration/tools_config_test.clj
+++ b/test/github/copilot_sdk/integration/tools_config_test.clj
@@ -86,18 +86,13 @@
       (is (= "sse" (get-in resume-params [:mcpServers :srv-2 :type])))
       (is (= "https://mcp.resume.test" (get-in resume-params [:mcpServers :srv-2 :url])))
       (is (= ["*"] (get-in resume-params [:mcpServers :srv-2 :tools])))
-      (is (= {:sessionId session-id
-              :config {:mcpServers
-                       {:srv-2 {:type "sse"
-                                :url "https://mcp.resume.test"
-                                :tools ["*"]}}}}
-             reload-params))
+      (is (nil? reload-params))
       (is (= "agent-2" (get-in resume-params [:customAgents 0 :name])))
       ;; envValueMode is always sent as "direct" (upstream PR #484)
       (is (= "direct" (:envValueMode create-params)))
       (is (= "direct" (:envValueMode resume-params))))))
 
-(deftest test-async-resume-reloads-mcp-configuration
+(deftest test-async-resume-configures-mcp-in-resume-request-only
   (let [seed (sdk/create-session *test-client* {})
         session-id (sdk/session-id seed)
         requests (atom [])
@@ -112,70 +107,36 @@
                   {"srv" {:mcp-server-type :http
                           :mcp-url "https://mcp.async.test"
                           :mcp-tools ["*"]}}}))
+        resume-request (some #(when (= "session.resume" (first %)) %) @requests)
         reloads (filter #(= "session.mcp.reloadWithConfig" (first %)) @requests)]
     (is (not (instance? Throwable result)))
-    (is (= [["session.mcp.reloadWithConfig"
-             {:sessionId session-id
-              :config {:mcpServers
-                       {:srv {:type "http"
-                              :url "https://mcp.async.test"
-                              :tools ["*"]}}}}]]
-           reloads))))
-
-(deftest test-sync-resume-cleans-up-after-mcp-reload-rpc-error
-  (let [seed (sdk/create-session *test-client* {})
-        session-id (sdk/session-id seed)]
-    (mock/set-request-hook!
-     *mock-server*
-     (fn [method _]
-       (when (= "session.mcp.reloadWithConfig" method)
-         (throw (ex-info "reload rejected" {:code -32042})))))
-    (is (thrown-with-msg?
-         clojure.lang.ExceptionInfo
-         #"reload rejected"
-         (sdk/resume-session
-          *test-client*
-          session-id
-          {:mcp-servers
-           {"srv" {:mcp-server-type :http
-                  :mcp-url "https://mcp.test"
-                  :mcp-tools ["*"]}}})))
-    (is (nil? (get-in @(:state *test-client*) [:sessions session-id])))))
-
-(deftest test-async-resume-cleans-up-after-mcp-reload-rpc-error
-  (let [seed (sdk/create-session *test-client* {})
-        session-id (sdk/session-id seed)]
-    (mock/set-request-hook!
-     *mock-server*
-     (fn [method _]
-       (when (= "session.mcp.reloadWithConfig" method)
-         (throw (ex-info "reload rejected" {:code -32042})))))
-    (let [result
-          (async/