pi-mcp-adapter 2.3.4 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.5] - 2026-04-13
11
+
12
+ ### Fixed
13
+ - Session lifecycle now always tears down OAuth callback state on restart and shutdown, preventing callback-server leaks across session transitions.
14
+ - OAuth callback server now calls `unref()` after successful bind so it no longer keeps sub-agent processes alive by itself.
15
+ - Strict OAuth port mode now rebinds to the configured callback port when safe, while refusing to switch ports when authorizations are still pending.
16
+ - Added focused lifecycle/callback-server regression coverage for teardown, `unref()`, strict rebinding, and pending-auth guardrails.
17
+ - Thanks @blai for the investigation and PR #43 that surfaced the sub-agent hang/root lifecycle issues.
18
+
10
19
  ## [2.3.4] - 2026-04-12
11
20
 
12
21
  ### Fixed
package/index.ts CHANGED
@@ -8,7 +8,7 @@ import { flushMetadataCache, initializeMcp, updateStatusBar } from "./init.js";
8
8
  import { loadMetadataCache } from "./metadata-cache.js";
9
9
  import { executeCall, executeConnect, executeDescribe, executeList, executeSearch, executeStatus, executeUiMessages } from "./proxy-modes.js";
10
10
  import { getConfigPathFromArgv, truncateAtWord } from "./utils.js";
11
- import { initializeOAuth } from "./mcp-auth-flow.js";
11
+ import { initializeOAuth, shutdownOAuth } from "./mcp-auth-flow.js";
12
12
 
13
13
  export default function mcpAdapter(pi: ExtensionAPI) {
14
14
  let state: McpExtensionState | null = null;
@@ -85,7 +85,10 @@ export default function mcpAdapter(pi: ExtensionAPI) {
85
85
  initPromise = null;
86
86
 
87
87
  try {
88
- await shutdownState(previousState, "session_restart");
88
+ await Promise.all([
89
+ shutdownState(previousState, "session_restart"),
90
+ shutdownOAuth(),
91
+ ]);
89
92
  } catch (error) {
90
93
  console.error("MCP: failed to shut down previous session state", error);
91
94
  }
@@ -133,7 +136,10 @@ export default function mcpAdapter(pi: ExtensionAPI) {
133
136
  initPromise = null;
134
137
 
135
138
  try {
136
- await shutdownState(currentState, "session_shutdown");
139
+ await Promise.all([
140
+ shutdownState(currentState, "session_shutdown"),
141
+ shutdownOAuth(),
142
+ ]);
137
143
  } catch (error) {
138
144
  console.error("MCP: session shutdown cleanup failed", error);
139
145
  }
@@ -155,9 +155,13 @@ export async function ensureCallbackServer(options: EnsureCallbackServerOptions
155
155
  if (server) {
156
156
  if (!strictPort || getOAuthCallbackPort() === configuredPort) return
157
157
 
158
- throw new Error(
159
- `OAuth callback server is already running on port ${getOAuthCallbackPort()}, but strict callback port ${configuredPort} is required`
160
- )
158
+ if (pendingAuths.size > 0) {
159
+ throw new Error(
160
+ `OAuth callback server is running on port ${getOAuthCallbackPort()}, but strict callback port ${configuredPort} is required and cannot be switched while authorizations are pending`
161
+ )
162
+ }
163
+
164
+ await stopCallbackServer()
161
165
  }
162
166
 
163
167
  const preferredPort = configuredPort
@@ -180,6 +184,7 @@ export async function ensureCallbackServer(options: EnsureCallbackServerOptions
180
184
  })
181
185
 
182
186
  server = candidateServer
187
+ server.unref()
183
188
  setOAuthCallbackPort(candidatePort)
184
189
  return
185
190
  } catch (error) {
@@ -257,7 +262,7 @@ export async function stopCallbackServer(): Promise<void> {
257
262
  const pendingList = Array.from(pendingAuths.entries())
258
263
  pendingAuths.clear()
259
264
  setTimeout(() => {
260
- for (const [state, pending] of pendingList) {
265
+ for (const [, pending] of pendingList) {
261
266
  clearTimeout(pending.timeout)
262
267
  pending.reject(new Error("OAuth callback server stopped"))
263
268
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mcp-adapter",
3
- "version": "2.3.4",
3
+ "version": "2.3.5",
4
4
  "description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",