pi-session-mcp 0.6.2 → 0.6.4

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.
@@ -1,11 +1,15 @@
1
+ import { fileURLToPath } from "node:url";
1
2
  import { parseDoctorArgs, renderDoctorHuman, renderDoctorJson, runDoctor } from "./doctor.js";
3
+ // The generated CLI lives one level below the package root. An npm executable runs
4
+ // from any directory, so the working directory says nothing about the package.
5
+ const PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));
2
6
  const options = parseDoctorArgs(process.argv.slice(2));
3
7
  if (!options) {
4
8
  process.stderr.write("Usage: doctor [--json]\n");
5
9
  process.exitCode = 64;
6
10
  }
7
11
  else {
8
- const result = await runDoctor();
12
+ const result = await runDoctor({ packageRoot: PACKAGE_ROOT });
9
13
  process.stdout.write(options.json ? renderDoctorJson(result) : renderDoctorHuman(result));
10
14
  process.exitCode = result.exitCode;
11
15
  }
@@ -104,8 +104,15 @@ export async function runDoctor(dependencies = {}) {
104
104
  const packageMtime = (await fs.stat(join(root, "package.json"))).mtimeMs;
105
105
  const lockMtime = await lockfileMtime(fs, root);
106
106
  const inputMtimes = [packageMtime, lockMtime].filter((value) => value !== undefined);
107
- if (!dependencies.fileSystem)
108
- inputMtimes.push(...await productionBuildInputMtimes(root));
107
+ if (!dependencies.fileSystem) {
108
+ const buildInputMtimes = await productionBuildInputMtimes(root);
109
+ // npm writes an installed package at extraction time in archive order, so without
110
+ // build inputs the manifest times say nothing about the freshness of the build.
111
+ if (buildInputMtimes.length === 0)
112
+ inputMtimes.length = 0;
113
+ else
114
+ inputMtimes.push(...buildInputMtimes);
115
+ }
109
116
  if (inputMtimes.some((mtime) => mtime > buildMtime))
110
117
  checks.push(warning("build_stale", "build output", "run the production build"));
111
118
  else
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.6.4 — 2026-10-10
6
+
7
+ - `pi-session-mcp-doctor` now checks the package it belongs to, whatever the
8
+ current directory is. Previously it checked the current directory: in an npm
9
+ installation, run from another directory, it failed with
10
+ `package_metadata_unreadable` and `build_missing`, and inside another
11
+ checkout it reported that checkout. `npm run doctor` in a release checkout
12
+ and `setup` were not affected.
13
+ - The installation guide and client setup reference now say that Codex
14
+ rewrites `config.toml` when a registration changes: it groups the
15
+ `[mcp_servers.*]` tables and drops comments directly above them. Copy the
16
+ file first if its comments matter.
17
+ - The client setup reference now explains that `codex exec` rejects
18
+ `pi_session_prompt`, `pi_session_abort` and `pi_session_close` unless they
19
+ are approved, because it never asks and the tools are marked destructive. It
20
+ shows the per-run `-c` approvals.
21
+
22
+ ## 0.6.3 — 2026-10-10
23
+
24
+ - Doctor no longer reports a false `build_stale` warning right after
25
+ `npm install` with npm 12. npm 12 writes extracted files with the extraction
26
+ time, and the package lists `dist/` before `package.json`, so the installed
27
+ manifest was always newer than the build. An installation without build
28
+ configuration or TypeScript sources no longer compares manifest times; a
29
+ source checkout still does.
30
+ - `setup` was re-recorded against Claude Code `2.1.296`; its `mcp` command
31
+ contract is unchanged.
32
+
5
33
  ## 0.6.2 — 2026-10-09
6
34
 
7
35
  - The server now shuts down when the MCP client closes its stdin. Previously
package/README.md CHANGED
@@ -29,7 +29,7 @@ It is not the right tool when:
29
29
 
30
30
  ## Status
31
31
 
32
- The package version is **0.6.2**.
32
+ The package version is **0.6.4**.
33
33
 
34
34
  - **Pre-1.0.** The public tool contract is stable within a minor line: a change to tools, fields, states or error codes needs a new minor release.
35
35
  - **Linux only**, Node.js 22.19.0 or newer.
@@ -1,11 +1,15 @@
1
+ import { fileURLToPath } from "node:url";
1
2
  import { parseDoctorArgs, renderDoctorHuman, renderDoctorJson, runDoctor } from "./doctor.js";
3
+ // The generated CLI lives one level below the package root. An npm executable runs
4
+ // from any directory, so the working directory says nothing about the package.
5
+ const PACKAGE_ROOT = fileURLToPath(new URL("..", import.meta.url));
2
6
  const options = parseDoctorArgs(process.argv.slice(2));
3
7
  if (!options) {
4
8
  process.stderr.write("Usage: doctor [--json]\n");
5
9
  process.exitCode = 64;
6
10
  }
7
11
  else {
8
- const result = await runDoctor();
12
+ const result = await runDoctor({ packageRoot: PACKAGE_ROOT });
9
13
  process.stdout.write(options.json ? renderDoctorJson(result) : renderDoctorHuman(result));
10
14
  process.exitCode = result.exitCode;
11
15
  }
package/dist/doctor.js CHANGED
@@ -104,8 +104,15 @@ export async function runDoctor(dependencies = {}) {
104
104
  const packageMtime = (await fs.stat(join(root, "package.json"))).mtimeMs;
105
105
  const lockMtime = await lockfileMtime(fs, root);
106
106
  const inputMtimes = [packageMtime, lockMtime].filter((value) => value !== undefined);
107
- if (!dependencies.fileSystem)
108
- inputMtimes.push(...await productionBuildInputMtimes(root));
107
+ if (!dependencies.fileSystem) {
108
+ const buildInputMtimes = await productionBuildInputMtimes(root);
109
+ // npm writes an installed package at extraction time in archive order, so without
110
+ // build inputs the manifest times say nothing about the freshness of the build.
111
+ if (buildInputMtimes.length === 0)
112
+ inputMtimes.length = 0;
113
+ else
114
+ inputMtimes.push(...buildInputMtimes);
115
+ }
109
116
  if (inputMtimes.some((mtime) => mtime > buildMtime))
110
117
  checks.push(warning("build_stale", "build output", "run the production build"));
111
118
  else
@@ -147,6 +147,9 @@ snapshot and digest tools and the scan for leaked values are prepared per cycle.
147
147
  - Clients: record the exact client versions and how each client reached the
148
148
  server. Prefer a temporary per-invocation MCP configuration, so that no
149
149
  global registration changes.
150
+ - Waiting: let each client wait a bounded time between `pi_turn_get` polls,
151
+ for example by allowing a shell `sleep` of a few seconds. A client that may
152
+ call only the Pi Session MCP tools has no way to wait and polls back to back.
150
153
  - Pre-registration: fix the plan, the acceptance criteria per task, the prompts,
151
154
  the oracles, the tools, the configurations and the fixture digests before the
152
155
  first task.
@@ -182,6 +185,10 @@ repeat a task.
182
185
  - Liveness: a running turn whose `updatedAt` advanced beyond `startedAt` shows
183
186
  observable activity. Its absence only means that the turn finished between
184
187
  two polls.
188
+ - Polling cost: count the `pi_turn_get` calls per turn. The counts are evidence
189
+ for the revisit trigger on bounded waiting in
190
+ [ADR 0003](adr/0003-post-mvp-maintenance.md) only when the client could wait
191
+ between polls.
185
192
 
186
193
  ### Gate
187
194
 
@@ -225,3 +232,40 @@ Release notes state which levels were run for a release and what was not
225
232
  covered. Pi Session MCP has passed all three levels in earlier private cycles. The
226
233
  live two-client acceptance has not yet been repeated on a build with Pi SDK
227
234
  `1.x`.
235
+
236
+ `v0.6.2` passed Level 1 on a fresh clone of its tag. It passed Level 2 in all
237
+ three variants: working tree, published release, and published npm package.
238
+ The clients were Codex CLI `0.162.0` (`user`) and Claude Code `2.1.295`
239
+ (`user`, `project`, `local`), on 2026-10-09 and 2026-10-10. It had no Level 3
240
+ cycle.
241
+
242
+ Before its release, `v0.6.3` passed Level 1 and the working-tree Level 2 on its
243
+ release candidate, with Claude Code `2.1.296`. On 2026-10-10 the same candidate
244
+ also passed a narrower live check:
245
+ - Scope: Claude Code `2.1.296` as the only client, with Pi SDK `1.1.0` on a
246
+ local `qwen3.6-35b-a3b-splash` model served by LM Studio.
247
+ - All five tasks of the matrix reached their intended outcome in three
248
+ sequential invocations, and every pre-registered check passed.
249
+ - It covered no Codex task and does not count as a ten-task cycle.
250
+
251
+ After its release, `v0.6.3` passed Level 1 on a fresh clone of its tag. It also
252
+ passed Level 2 as published release and as published npm package, with Codex
253
+ CLI `0.162.0` and Claude Code `2.1.296`, on 2026-10-10.
254
+
255
+ On 2026-10-10, `main` at `4d333da`, which is `v0.6.3` plus the Doctor fix and
256
+ documentation, passed a narrower live check with Codex:
257
+ - Scope: Codex CLI `0.162.0` as the only client, run headless with
258
+ `codex exec` and the three tool approvals that
259
+ [client setup](client-setup.md#run-codex-without-prompts) describes. Pi SDK
260
+ `1.1.0` ran on the same local model.
261
+ - All five tasks of the matrix reached their intended outcome in three
262
+ sequential invocations, and every pre-registered check passed.
263
+ - The client could wait between polls and needed 1 to 3 `pi_turn_get` calls per
264
+ turn.
265
+ - It covered no Claude Code task and does not count as a ten-task cycle. The
266
+ Claude Code check above ran on another commit.
267
+
268
+ Before its release, `v0.6.4` passed Level 1 and the working-tree Level 2 on its
269
+ release candidate, with Codex CLI `0.162.0` and Claude Code `2.1.296`. Its
270
+ server entry point `dist/main.js` is byte-identical to that of `4d333da` and of
271
+ `v0.6.3`.
@@ -122,6 +122,37 @@ codex mcp list
122
122
  codex mcp get pi-session-mcp
123
123
  ```
124
124
 
125
+ `codex mcp add` and `codex mcp remove` rewrite `config.toml`. Codex CLI
126
+ `0.162.0` groups all `[mcp_servers.*]` tables together and drops a comment
127
+ directly above such a table; settings are preserved. Copy the file first if its
128
+ comments matter to you.
129
+
130
+ ### Run Codex without prompts
131
+
132
+ Interactive Codex asks before it calls a tool that is marked
133
+ `destructiveHint: true`: `pi_session_prompt`, `pi_session_abort` and
134
+ `pi_session_close`. `codex exec` never asks, so Codex CLI `0.162.0` rejects
135
+ these calls with "MCP tool call requires approval, but approval policy is
136
+ never". A headless run can then start sessions but cannot prompt, abort or
137
+ close them.
138
+
139
+ Approve the three tools for each headless run:
140
+
141
+ ```bash
142
+ codex exec \
143
+ -c 'mcp_servers.pi-session-mcp.tools.pi_session_prompt.approval_mode="approve"' \
144
+ -c 'mcp_servers.pi-session-mcp.tools.pi_session_abort.approval_mode="approve"' \
145
+ -c 'mcp_servers.pi-session-mcp.tools.pi_session_close.approval_mode="approve"' \
146
+ 'Your task'
147
+ ```
148
+
149
+ The same `approval_mode` entries can live in `config.toml` under
150
+ `[mcp_servers.pi-session-mcp.tools.<tool>]`. They do not change the output of
151
+ `codex mcp get`, so `setup` still treats the registration as equal. But
152
+ `codex mcp remove`, which `setup --remove` and `--rollback` use, deletes them,
153
+ so they are gone after an upgrade. The per-run overrides do not have this
154
+ problem.
155
+
125
156
  ## Register with Claude Code
126
157
 
127
158
  Claude Code CLI 2.1.251 was locally confirmed with this command form. Replace every absolute-path placeholder with your local paths; use absolute paths for the Node executable, built entry point, and configuration file.
@@ -3,6 +3,8 @@
3
3
  `src/doctor-cli.ts` is a separate local entry point. It never imports the MCP
4
4
  server, initializes transport, creates a Pi session, reads credentials, or
5
5
  performs network activity.
6
+ It checks the package it was loaded from, never the current working
7
+ directory: an npm executable can run from any directory.
6
8
 
7
9
  `runDoctor` returns one frozen result model (`schemaVersion: 1`, `ok`, a
8
10
  sanitized semver `packageVersion` when metadata is available, ordered `checks`,
@@ -20,7 +22,7 @@ and owners are:
20
22
  | `node_version_unsupported` | Runtime does not satisfy `package.json#engines.node` | `Node.js` |
21
23
  | `package_metadata_unreadable` | Package metadata is missing, unreadable or malformed, or a lockfile is present but malformed | `package metadata` |
22
24
  | `build_missing` | `dist/main.js` is absent, inaccessible, or not a regular file | `build output` |
23
- | `build_stale` | Package, lock, build configuration, or production TypeScript input is newer than the build output, or freshness cannot be established. Inputs that an npm installation does not contain are skipped | `build output` |
25
+ | `build_stale` | Package, lock, build configuration, or production TypeScript input is newer than the build output, or freshness cannot be established. Inputs that an npm installation does not contain are skipped. Without any build configuration or TypeScript input, as in an npm installation, the package and lock times are not compared either, because npm writes extracted files with the extraction time | `build output` |
24
26
  | `version_mismatch` | Package and lock versions differ; this is a warning and does not apply to an npm installation, which has no lockfile | `package version` |
25
27
  | `config_missing` | `PI_SESSION_MCP_CONFIG` is not set, or the file it names is absent | `configuration` |
26
28
  | `config_unreadable` | The supported configuration path cannot be read | `configuration` |
@@ -47,7 +47,7 @@ the same arguments.
47
47
  - Codex CLI or Claude Code. `setup` does not pin client versions. It accepts a
48
48
  client whose public `mcp` command output matches the expected contract and
49
49
  reports `unsupported` otherwise. The contract was last recorded with Codex CLI
50
- `0.162.0` and Claude Code `2.1.295`. Manual registration, described in the
50
+ `0.162.0` and Claude Code `2.1.296`. Manual registration, described in the
51
51
  [client setup reference](client-setup.md), works independently of `setup`.
52
52
  - For real prompts only: local Pi authentication and a provider and model pair
53
53
  that the local Pi configuration knows. Installation, Doctor and `setup` need
@@ -207,6 +207,13 @@ pi-session-mcp-setup --apply --target claude-code:user:pi-session-mcp
207
207
  pi-session-mcp-setup --verify --target claude-code:user:pi-session-mcp
208
208
  ```
209
209
 
210
+ `setup` changes a Codex registration only through `codex mcp add` and
211
+ `codex mcp remove`, and Codex rewrites `config.toml` on each of them. Codex CLI
212
+ `0.162.0` groups all `[mcp_servers.*]` tables together and drops a comment
213
+ directly above such a table; settings are preserved. If your `config.toml`
214
+ contains comments worth keeping, copy it before `--apply`, `--rollback` or
215
+ `--remove` on `codex:user:pi-session-mcp`.
216
+
210
217
  Each report has one line for the operation with its overall status, and one line
211
218
  per target with a finding in the form `status (code)`:
212
219
 
@@ -22,7 +22,7 @@ There are exactly eight tools. No `pi_turn_wait` tool or live provider/model inv
22
22
  ```json
23
23
  {
24
24
  "ok": true,
25
- "server": { "name": "pi-session-mcp", "version": "0.6.2" },
25
+ "server": { "name": "pi-session-mcp", "version": "0.6.4" },
26
26
  "configuration": {
27
27
  "fingerprint": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
28
28
  "reloadPolicy": "restart-required"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-session-mcp",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Local stdio MCP server for controlled Pi coding-agent sessions",
5
5
  "license": "MIT",
6
6
  "keywords": [