pi-session-mcp 0.7.1 → 0.8.0
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/.pi-session-mcp-cli/config.js +47 -7
- package/.pi-session-mcp-cli/doctor.js +68 -2
- package/.pi-session-mcp-cli/execution-profile.js +1 -0
- package/.pi-session-mcp-cli/setup-result.js +8 -0
- package/.pi-session-mcp-cli/skill-catalog.js +35 -0
- package/.pi-session-mcp-cli/skill-customize.js +183 -0
- package/.pi-session-mcp-cli/skill-library.js +120 -0
- package/CHANGELOG.md +85 -0
- package/README.md +15 -3
- package/dist/capabilities.d.ts +1 -0
- package/dist/capabilities.js +2 -1
- package/dist/client-adapters/mcp-verifier.js +6 -2
- package/dist/config.d.ts +4 -0
- package/dist/config.js +47 -7
- package/dist/doctor.d.ts +4 -1
- package/dist/doctor.js +68 -2
- package/dist/execution-profile.d.ts +4 -0
- package/dist/execution-profile.js +1 -0
- package/dist/pi-adapter.d.ts +1 -1
- package/dist/pi-adapter.js +1 -0
- package/dist/pi-skills.d.ts +17 -0
- package/dist/pi-skills.js +64 -0
- package/dist/sdk-pi-adapter.d.ts +7 -3
- package/dist/sdk-pi-adapter.js +54 -11
- package/dist/server.js +1 -0
- package/dist/setup-cli.d.ts +2 -0
- package/dist/setup-cli.js +16 -0
- package/dist/setup-main.d.ts +1 -1
- package/dist/setup-main.js +18 -3
- package/dist/setup-ownership.d.ts +6 -0
- package/dist/setup-ownership.js +29 -5
- package/dist/setup-skills.d.ts +37 -0
- package/dist/setup-skills.js +353 -0
- package/dist/setup.d.ts +7 -0
- package/dist/setup.js +49 -6
- package/dist/skill-catalog.d.ts +26 -0
- package/dist/skill-catalog.js +35 -0
- package/dist/skill-customize.d.ts +23 -0
- package/dist/skill-customize.js +183 -0
- package/dist/skill-library.d.ts +61 -0
- package/dist/skill-library.js +120 -0
- package/docs/acceptance.md +243 -1
- package/docs/adr/0006-pi-extension-allowlist.md +3 -0
- package/docs/adr/0007-profile-skill-selection.md +217 -0
- package/docs/architecture.md +9 -5
- package/docs/client-setup-design.md +133 -1
- package/docs/client-setup.md +74 -3
- package/docs/doctor-design.md +9 -1
- package/docs/installation.md +122 -5
- package/docs/pi-extensions-design.md +17 -4
- package/docs/session-mcp.md +7 -2
- package/docs/skills.md +487 -0
- package/docs/threat-model.md +19 -2
- package/docs/tool-contracts.md +8 -4
- package/package.json +2 -1
- package/pi-session-mcp.example.json +9 -3
- package/skills/pi-session-implementation/SKILL.md +42 -0
- package/skills/pi-session-orchestration/SKILL.md +93 -0
- package/skills/pi-session-review/SKILL.md +58 -0
package/docs/skills.md
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
# Pi skills in execution profiles
|
|
2
|
+
|
|
3
|
+
Status: decided in [ADR 0007](adr/0007-profile-skill-selection.md), issue
|
|
4
|
+
[#46](https://github.com/plagor44-ux/pi-session-mcp/issues/46).
|
|
5
|
+
|
|
6
|
+
A Pi skill is a `SKILL.md` file with instructions that Pi lists to the model in
|
|
7
|
+
its system prompt. The model may read the file when a task matches the skill's
|
|
8
|
+
description. Pi Session MCP lets the operator register skill files in a catalog
|
|
9
|
+
and select them per execution profile. MCP callers never choose skills.
|
|
10
|
+
|
|
11
|
+
The package ships three skills and keeps them in a skill library together with
|
|
12
|
+
the operator's own overrides. `pi-session-mcp-setup --apply` also installs the
|
|
13
|
+
controller skill into Claude Code and Codex. Nothing needs to be linked by hand.
|
|
14
|
+
Sections: [Configuration](#configuration), [The skill library](#the-skill-library),
|
|
15
|
+
[Customize and add skills](#customize-and-add-skills) and [Install the
|
|
16
|
+
orchestration skill into Codex and Claude Code](#install-the-orchestration-skill-into-codex-and-claude-code).
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
Two optional parts of `pi-session-mcp.json`:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"workspaces": {
|
|
25
|
+
"my-project": "/absolute/path/to/my-project"
|
|
26
|
+
},
|
|
27
|
+
"skillCatalog": {
|
|
28
|
+
"pi-session-implementation": "builtin:pi-session-implementation",
|
|
29
|
+
"pi-session-review": "builtin:pi-session-review",
|
|
30
|
+
"release-notes": "skills-local/release-notes/SKILL.md"
|
|
31
|
+
},
|
|
32
|
+
"executionProfiles": {
|
|
33
|
+
"safe-readonly": {
|
|
34
|
+
"default": true,
|
|
35
|
+
"permissionProfile": "read-only",
|
|
36
|
+
"provider": "your-configured-provider",
|
|
37
|
+
"model": "your-configured-model",
|
|
38
|
+
"thinkingLevel": "medium",
|
|
39
|
+
"skills": ["pi-session-review"]
|
|
40
|
+
},
|
|
41
|
+
"coding-worker": {
|
|
42
|
+
"default": false,
|
|
43
|
+
"permissionProfile": "coding",
|
|
44
|
+
"provider": "your-configured-provider",
|
|
45
|
+
"model": "your-configured-model",
|
|
46
|
+
"thinkingLevel": "high",
|
|
47
|
+
"skills": ["pi-session-implementation", "release-notes"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Catalog: `skillCatalog`
|
|
54
|
+
|
|
55
|
+
- An optional top-level object that maps a skill alias to the path of a
|
|
56
|
+
`SKILL.md` file. A missing catalog is an empty catalog.
|
|
57
|
+
- At most 64 entries. An alias matches `^[a-z][a-z0-9_-]{0,63}$`, like every
|
|
58
|
+
other alias.
|
|
59
|
+
- Each value is either `builtin:<name>` or names exactly one regular, readable
|
|
60
|
+
file whose last path segment is `SKILL.md`. `builtin:<name>` refers to a
|
|
61
|
+
skill of the [skill library](#the-skill-library); `<name>` must follow the
|
|
62
|
+
skill name rule below, and `builtin:` followed by anything else is rejected.
|
|
63
|
+
Directories, globs, URLs and every other scheme-prefixed source (`npm:`,
|
|
64
|
+
`git+…`, `https:`) are rejected. So are `~` and backslashes. A value has at
|
|
65
|
+
most 4096 characters.
|
|
66
|
+
- A relative path resolves against the directory of the configuration file,
|
|
67
|
+
like a workspace. It never resolves against a workspace or the shell's
|
|
68
|
+
working directory. `~` is not expanded: write an absolute path, or use
|
|
69
|
+
`builtin:<name>` for a library skill.
|
|
70
|
+
- A skill folder needs no `package.json` and no extension. The file can live
|
|
71
|
+
anywhere the server's OS user can read. Keep catalog files outside every
|
|
72
|
+
configured workspace: a `coding` session can change any file in its
|
|
73
|
+
workspace, and a changed skill reaches other sessions too (see
|
|
74
|
+
[snapshot semantics](#snapshot-semantics)).
|
|
75
|
+
- The catalog alias is only the public handle. It may differ from the `name` in
|
|
76
|
+
the skill's own frontmatter. Nothing is renamed.
|
|
77
|
+
|
|
78
|
+
### Selection: `executionProfiles.<alias>.skills`
|
|
79
|
+
|
|
80
|
+
- An optional list of catalog aliases, at most 16, no duplicates.
|
|
81
|
+
- Missing or empty means no skills for that profile. There is no inheritance
|
|
82
|
+
between profiles and no default skill.
|
|
83
|
+
- All other profile fields and the rule that unknown fields are rejected are
|
|
84
|
+
unchanged.
|
|
85
|
+
|
|
86
|
+
### Invalid configuration
|
|
87
|
+
|
|
88
|
+
These make the whole configuration invalid. The server does not start, and
|
|
89
|
+
Doctor reports `config_invalid`. Stderr shows the stable startup code
|
|
90
|
+
`invalid_execution_profile_config`:
|
|
91
|
+
|
|
92
|
+
- a selected alias that is not in the catalog;
|
|
93
|
+
- a duplicate alias in one profile's list;
|
|
94
|
+
- two selected aliases of one profile whose paths resolve to the same path,
|
|
95
|
+
for example two aliases for `builtin:pi-session-review`;
|
|
96
|
+
- a catalog value that violates the rules above (including a malformed
|
|
97
|
+
`builtin:` name), or more than 64 entries;
|
|
98
|
+
- more than 16 selected aliases.
|
|
99
|
+
|
|
100
|
+
## The skill library
|
|
101
|
+
|
|
102
|
+
The skill library has two sources and nothing else:
|
|
103
|
+
|
|
104
|
+
1. **Shipped skills.** The package's `skills/` directory.
|
|
105
|
+
2. **Operator overrides.** A `skills/` directory next to the configuration
|
|
106
|
+
file, that is, in the directory of the path in `PI_SESSION_MCP_CONFIG`. For
|
|
107
|
+
the default location `~/.config/pi-session-mcp/pi-session-mcp.json` it is
|
|
108
|
+
`~/.config/pi-session-mcp/skills/<name>/SKILL.md`.
|
|
109
|
+
|
|
110
|
+
An override with the same name replaces the shipped skill. A name that is not
|
|
111
|
+
shipped adds a skill. A name follows the Agent Skills rule: lowercase letters
|
|
112
|
+
and digits in hyphen-separated groups, 1 to 64 characters. No other directory
|
|
113
|
+
is searched: not the current directory, not a workspace and not a client's
|
|
114
|
+
skill directory.
|
|
115
|
+
|
|
116
|
+
### `builtin:<name>` in the catalog
|
|
117
|
+
|
|
118
|
+
A catalog value `builtin:<name>` resolves to `<override dir>/<name>/SKILL.md`
|
|
119
|
+
if that file exists, else to the shipped skill of that name. If neither
|
|
120
|
+
exists, the value keeps the shipped location. Nothing fails when the
|
|
121
|
+
configuration loads, but Doctor then reports `skill_missing` for the profile
|
|
122
|
+
that selects it, and a session start fails with `skill_load_failed`.
|
|
123
|
+
|
|
124
|
+
Resolution happens when the server loads the configuration. Adding or removing
|
|
125
|
+
an override therefore needs a server restart, like any configuration change.
|
|
126
|
+
Edits to a skill file that already resolves reach new sessions, as described
|
|
127
|
+
under [snapshot semantics](#snapshot-semantics). Deleting a resolved override
|
|
128
|
+
leaves the catalog pointing at a missing file until the restart.
|
|
129
|
+
|
|
130
|
+
The shipped example configuration registers the two worker skills with
|
|
131
|
+
`builtin:`. After you copy the example, its skill entries need no path edits.
|
|
132
|
+
|
|
133
|
+
### Shipped skills
|
|
134
|
+
|
|
135
|
+
The package ships three skills under `skills/`. Each has one canonical copy and
|
|
136
|
+
frontmatter with only `name` and `description`.
|
|
137
|
+
|
|
138
|
+
| Skill | For | Use |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `pi-session-implementation` | A Pi worker | One bounded implementation task and a fixed final report. Register it as `builtin:pi-session-implementation` and select it on coding profiles. |
|
|
141
|
+
| `pi-session-review` | A Pi worker | A review of a fixed target with findings and evidence. Register it as `builtin:pi-session-review` and select it on read-only profiles. |
|
|
142
|
+
| `pi-session-orchestration` | The controlling Claude Code or Codex agent | How to run Pi worker sessions through this server. `setup --apply` installs it into the clients. It is not a Pi worker skill: do not select it in a profile. |
|
|
143
|
+
|
|
144
|
+
A package update can change the shipped skills. Close affected sessions before
|
|
145
|
+
you update, as for any skill change.
|
|
146
|
+
|
|
147
|
+
## Customize and add skills
|
|
148
|
+
|
|
149
|
+
Do not edit the files inside the installed package: an update replaces them.
|
|
150
|
+
Put your version in the override directory.
|
|
151
|
+
|
|
152
|
+
### Customize a shipped skill
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
export PI_SESSION_MCP_CONFIG="$HOME/.config/pi-session-mcp/pi-session-mcp.json"
|
|
156
|
+
pi-session-mcp-setup --customize-skill pi-session-review # dry-run
|
|
157
|
+
pi-session-mcp-setup --apply --customize-skill pi-session-review
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The dry-run reports what would happen, for example:
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
dry-run: planned
|
|
164
|
+
skills/override/pi-session-review: planned (skill_customize_planned)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`--apply` copies the shipped skill directory into the override directory as a
|
|
168
|
+
starting point and records the fingerprint of the shipped skill in
|
|
169
|
+
`<override dir>/.pi-session-mcp-bases.json`. Then edit
|
|
170
|
+
`<override dir>/pi-session-review/SKILL.md`, restart the server so that the new
|
|
171
|
+
override is picked up, and start new sessions.
|
|
172
|
+
|
|
173
|
+
- The command works without `--target`; it touches no client. It cannot be
|
|
174
|
+
combined with `--target`, `--verify`, `--rollback` or `--remove`, which are
|
|
175
|
+
usage errors (exit 64).
|
|
176
|
+
- It requires `PI_SESSION_MCP_CONFIG` (otherwise `config_required`) and the
|
|
177
|
+
same platform as the rest of `setup`: Linux or macOS, otherwise
|
|
178
|
+
`platform_unsupported`. It takes no ownership lock.
|
|
179
|
+
- It never overwrites an existing override and never edits your files.
|
|
180
|
+
- Only regular files are copied: at most 32 files, 1 MiB and 8 directory
|
|
181
|
+
levels, no links, and entries whose name starts with `.` are skipped.
|
|
182
|
+
|
|
183
|
+
The finding target is `{ client: "skills", scope: "override", alias: <name> }`:
|
|
184
|
+
|
|
185
|
+
| Code | Status | Meaning |
|
|
186
|
+
| --- | --- | --- |
|
|
187
|
+
| `skill_customize_planned` | planned | Dry-run: no override exists; `--apply` would copy the shipped skill. |
|
|
188
|
+
| `skill_customized` | ok | The override was created and its base recorded. |
|
|
189
|
+
| `skill_override_current` | unchanged | The override exists and its recorded base equals the current shipped skill. |
|
|
190
|
+
| `skill_override_outdated` | planned | The shipped skill changed since the copy, or no base is recorded for the existing override. |
|
|
191
|
+
| `skill_base_updated` | ok | `--apply` after `skill_override_outdated`: only the recorded base moved. |
|
|
192
|
+
| `skill_not_shipped` | failed | The name is not valid or the package ships no such skill. |
|
|
193
|
+
| `skill_bases_corrupt` | failed | The bases file is not valid. Repair or remove it. |
|
|
194
|
+
| `skill_override_invalid` | failed | The override entry is not a directory, or its tree is unusable (no `SKILL.md`, a link, too large). |
|
|
195
|
+
| `skill_customize_failed` | failed | Any other failure while copying or recording. |
|
|
196
|
+
|
|
197
|
+
### Follow a changed shipped skill
|
|
198
|
+
|
|
199
|
+
After a package update, `skill_override_outdated` (from the command above, or
|
|
200
|
+
as a [Doctor](#doctor-boundary) warning) means that the shipped skill differs
|
|
201
|
+
from the one your override was copied from. Review the shipped text, merge what
|
|
202
|
+
you want into your override by hand, and then acknowledge it:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
pi-session-mcp-setup --apply --customize-skill pi-session-review
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
That moves only the recorded base (`skill_base_updated`). It never touches your
|
|
209
|
+
files. The override keeps winning until you delete it; the base only decides
|
|
210
|
+
whether Doctor warns.
|
|
211
|
+
|
|
212
|
+
### Add a new skill
|
|
213
|
+
|
|
214
|
+
No command is needed. Create `<override dir>/<new-name>/SKILL.md` (a valid
|
|
215
|
+
Agent Skills file with `name` and `description` frontmatter), reference it as
|
|
216
|
+
`builtin:<new-name>` in `skillCatalog`, select its alias in a profile, and
|
|
217
|
+
restart the server. Companion files belong in the same directory. A name that
|
|
218
|
+
equals a shipped skill replaces that skill instead of adding one.
|
|
219
|
+
|
|
220
|
+
Where `setup` is unsupported, create an override by copying a shipped skill
|
|
221
|
+
directory by hand. Doctor does not track a copy that has no recorded base.
|
|
222
|
+
|
|
223
|
+
## Install the orchestration skill into Codex and Claude Code
|
|
224
|
+
|
|
225
|
+
The orchestration skill is for the controlling agent, not for a Pi worker.
|
|
226
|
+
`pi-session-mcp-setup --apply --target <target>` installs it after the
|
|
227
|
+
registration, as a real copy of the effective skill: your override if you have
|
|
228
|
+
one, else the shipped skill. Clients discover it without further steps.
|
|
229
|
+
|
|
230
|
+
| Target | Skill directory |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| `codex:user:pi-session-mcp` | `~/.agents/skills/pi-session-orchestration` |
|
|
233
|
+
| `claude-code:user:pi-session-mcp` and `claude-code:local:pi-session-mcp` | `~/.claude/skills/pi-session-orchestration` (one shared directory) |
|
|
234
|
+
| `claude-code:project:pi-session-mcp` | `<project>/.claude/skills/pi-session-orchestration`, where `<project>` is the directory in which `setup` runs |
|
|
235
|
+
|
|
236
|
+
Claude Code reads personal skills in `~/.claude/skills/<name>/SKILL.md` and
|
|
237
|
+
project skills in `.claude/skills/<name>/SKILL.md`
|
|
238
|
+
([Claude Code skills](https://code.claude.com/docs/en/skills)). Codex reads user
|
|
239
|
+
skills in `~/.agents/skills`
|
|
240
|
+
([Codex skills](https://learn.chatgpt.com/docs/build-skills)).
|
|
241
|
+
|
|
242
|
+
Every `setup` result has a second finding per target, with the same client and
|
|
243
|
+
scope and the alias `pi-session-orchestration`. A skill problem never blocks
|
|
244
|
+
the registration, but a `divergent` or `failed` skill finding makes the overall
|
|
245
|
+
status `failed` (exit 1), so it is not overlooked.
|
|
246
|
+
|
|
247
|
+
| Operation | Code (status) |
|
|
248
|
+
| --- | --- |
|
|
249
|
+
| `--dry-run` | `skill_absent` (absent), `skill_equivalent` (unchanged), `skill_linked` (unchanged), `skill_update_planned` (planned), `skill_divergent` (divergent), `skill_source_invalid` (failed) |
|
|
250
|
+
| `--apply` | `skill_installed` (ok), `skill_already_equivalent` (unchanged), `skill_linked` (unchanged), `skill_updated` (ok), `skill_divergent` (divergent), `skill_source_invalid` (failed), `skill_install_failed` (failed) |
|
|
251
|
+
| `--verify` | `skill_verified` (ok), `skill_missing` (failed), `skill_not_equivalent` (failed) |
|
|
252
|
+
| `--rollback`, `--remove` | `skill_removed` (ok), `skill_kept_shared` (unchanged), `skill_not_owned` (unchanged), `skill_absent` (ok), `skill_divergent` (divergent) |
|
|
253
|
+
|
|
254
|
+
- `--apply` installs the skill only when the registration finding is `ok` or
|
|
255
|
+
`unchanged`; `--rollback` and `--remove` handle it only after the
|
|
256
|
+
registration was removed.
|
|
257
|
+
- `skill_updated` means that setup replaced its own unmodified copy after a
|
|
258
|
+
package update or a changed override.
|
|
259
|
+
- `skill_kept_shared` means that the other Claude Code registration (`user` or
|
|
260
|
+
`local`) still uses the shared directory. The last one removes the skill.
|
|
261
|
+
- A copy that already equals the effective skill but was not created by `setup`
|
|
262
|
+
is reported as equivalent and stays unowned; a later `--remove` reports
|
|
263
|
+
`skill_not_owned`.
|
|
264
|
+
- `--verify` compares the installed copy with the effective skill and does not
|
|
265
|
+
look at ownership.
|
|
266
|
+
|
|
267
|
+
### What setup never replaces or deletes
|
|
268
|
+
|
|
269
|
+
Setup reports `skill_divergent` and leaves the entry alone when it finds:
|
|
270
|
+
|
|
271
|
+
- an installed copy that was modified after setup wrote it;
|
|
272
|
+
- a skill of the same name that setup did not install and that differs from the
|
|
273
|
+
effective skill;
|
|
274
|
+
- any entry whose name starts with `.` inside an installed copy, such as your
|
|
275
|
+
own notes or a `.DS_Store` that macOS Finder adds: setup never writes such
|
|
276
|
+
entries, so it treats them as yours; delete them to let setup manage the copy
|
|
277
|
+
again;
|
|
278
|
+
- a link at the skill entry that points anywhere but the effective skill, or a
|
|
279
|
+
non-directory there.
|
|
280
|
+
|
|
281
|
+
A link at the skill entry that points exactly at the effective skill (your
|
|
282
|
+
override, else the shipped skill) is your own equivalent setup: setup reports
|
|
283
|
+
`skill_linked` (unchanged), `--verify` reports `skill_verified`, and removal
|
|
284
|
+
leaves the link alone (`skill_not_owned`). If you replace setup's own copy with
|
|
285
|
+
such a link, setup forgets its copy on the next `--apply` or `--remove`. A link
|
|
286
|
+
counts only while the effective skill itself is valid.
|
|
287
|
+
|
|
288
|
+
If an update is interrupted, for example by a full disk or a signal, setup still
|
|
289
|
+
recognizes the old copy as its own: the next `--apply` finishes the update and
|
|
290
|
+
`--remove` deletes it. A project copy belongs to its project: setup records an
|
|
291
|
+
opaque project identity, so a `--remove` in another project never deletes it.
|
|
292
|
+
|
|
293
|
+
Links in the path to the entry are handled by place. In your home directory,
|
|
294
|
+
the client's skill directory may be your own link, for example into a dotfiles
|
|
295
|
+
checkout, and is followed. Inside a project, which may be untrusted, any link
|
|
296
|
+
below the project root makes the entry divergent, so setup never writes outside
|
|
297
|
+
the project.
|
|
298
|
+
|
|
299
|
+
### Customize the controller skill
|
|
300
|
+
|
|
301
|
+
Never edit the installed copy: it becomes divergent. Instead:
|
|
302
|
+
|
|
303
|
+
1. `pi-session-mcp-setup --apply --customize-skill pi-session-orchestration`
|
|
304
|
+
2. Edit `<override dir>/pi-session-orchestration/SKILL.md`.
|
|
305
|
+
3. `pi-session-mcp-setup --apply --target <target>` again. The unmodified
|
|
306
|
+
installed copy is replaced (`skill_updated`).
|
|
307
|
+
|
|
308
|
+
To recover after editing the installed copy, move your edits into the override,
|
|
309
|
+
delete the installed copy, and run `--apply` again.
|
|
310
|
+
|
|
311
|
+
### Scope of what setup installs
|
|
312
|
+
|
|
313
|
+
Setup installs only `pi-session-orchestration` into clients. The worker skills
|
|
314
|
+
are for Pi profiles and are used through `builtin:`. Controller skills of your
|
|
315
|
+
own belong in the clients' native skill directories; setup does not manage
|
|
316
|
+
them.
|
|
317
|
+
|
|
318
|
+
### Install by hand where setup is unsupported
|
|
319
|
+
|
|
320
|
+
Where `setup` does not run, copy the directory; do not link it. Copy
|
|
321
|
+
`skills/pi-session-orchestration` from the installed package (in an npm
|
|
322
|
+
installation `"$(npm root -g)/pi-session-mcp/skills/pi-session-orchestration"`)
|
|
323
|
+
to `~/.claude/skills/` or `.claude/skills/` of a project for Claude Code, or to
|
|
324
|
+
`~/.agents/skills/` for Codex. Repeat the copy after a package update; nothing
|
|
325
|
+
keeps a manual copy current. Do not replace an existing skill of the same name
|
|
326
|
+
without checking it first.
|
|
327
|
+
|
|
328
|
+
Neither client needs a skill to call the Pi Session MCP tools; the skill only
|
|
329
|
+
describes the working method. Headless `codex exec` runs still need the
|
|
330
|
+
per-tool approvals for `pi_session_prompt`, `pi_session_abort` and
|
|
331
|
+
`pi_session_close` that [client
|
|
332
|
+
setup](client-setup.md#run-codex-without-prompts) describes.
|
|
333
|
+
|
|
334
|
+
### Pi workers
|
|
335
|
+
|
|
336
|
+
Pi workers never discover skills on their own in Pi Session MCP. Register the
|
|
337
|
+
worker skills with `builtin:` and select them on profiles, as described above.
|
|
338
|
+
Do not select the orchestration skill for a Pi worker: a worker has only the
|
|
339
|
+
tools of its profile and is not a controller of other Pi sessions.
|
|
340
|
+
|
|
341
|
+
## What happens at session start
|
|
342
|
+
|
|
343
|
+
The server loads exactly the selected files through the Pi SDK's public
|
|
344
|
+
`loadSkills`, without any default directories, and validates them completely.
|
|
345
|
+
The SDK's skill override returns exactly that set, also after an extension adds
|
|
346
|
+
resources later (`resources_discover`). A profile without skills gets no
|
|
347
|
+
skills, whatever is installed on the machine or shipped by an extension.
|
|
348
|
+
|
|
349
|
+
The start fails with `skill_load_failed` (message `Configured Pi skill could
|
|
350
|
+
not be loaded`) if:
|
|
351
|
+
|
|
352
|
+
- a selected file is missing, unreadable, or larger than 256 KiB (also a
|
|
353
|
+
`builtin:` value that resolved to no skill);
|
|
354
|
+
- the SDK reports the skill as invalid, for example a missing description or an
|
|
355
|
+
invalid name;
|
|
356
|
+
- two selected files declare the same Pi skill name;
|
|
357
|
+
- two aliases point at the same canonical file, for example through a symlink;
|
|
358
|
+
- the skill sets `disable-model-invocation: true`.
|
|
359
|
+
|
|
360
|
+
The message is fixed. It never contains a path, a skill name or SDK text.
|
|
361
|
+
Stderr gets a structured diagnostic. A selected file that fails validation
|
|
362
|
+
reports the stage `skill_load` and, when one alias is to blame, that catalog
|
|
363
|
+
alias in a `skill` field. If the session's actual skill catalog differs from
|
|
364
|
+
the selection after construction, the stage is `postcheck`, or
|
|
365
|
+
`extension_load` and `extension_bind` for a profile with extensions. Neither
|
|
366
|
+
carries a path.
|
|
367
|
+
|
|
368
|
+
If the session's prompt-template or theme catalog is not empty after
|
|
369
|
+
construction, which the overrides should prevent, the start fails with
|
|
370
|
+
`pi_session_creation_failed`.
|
|
371
|
+
|
|
372
|
+
Explicit-only skills (`disable-model-invocation: true`) are incompatible in
|
|
373
|
+
this version. Pi hides such skills from the model, and MCP prompts never run
|
|
374
|
+
`/skill:` commands, so the skill could never be used. The server does not
|
|
375
|
+
rewrite the flag. The same Pi skill name in different sessions is fine.
|
|
376
|
+
|
|
377
|
+
## Doctor boundary
|
|
378
|
+
|
|
379
|
+
Doctor stays offline and never parses or executes a skill. For each profile and
|
|
380
|
+
selected alias it adds three checks after the extension checks, with the
|
|
381
|
+
subject `<profile>:<skill-alias>`. A `builtin:` alias is checked at the
|
|
382
|
+
location it resolved to:
|
|
383
|
+
|
|
384
|
+
| ID | Condition |
|
|
385
|
+
| --- | --- |
|
|
386
|
+
| `skill_missing` | The selected file does not exist. |
|
|
387
|
+
| `skill_unreadable` | The path is not a regular file, is over 256 KiB, or cannot be read. |
|
|
388
|
+
| `skill_duplicate` | Two selected aliases of one profile resolve to the same canonical file. |
|
|
389
|
+
|
|
390
|
+
Frontmatter, name rules, name collisions and the explicit-only flag are checked
|
|
391
|
+
only at session start by the SDK contract. A clean Doctor run therefore does
|
|
392
|
+
not promise that the skill loads.
|
|
393
|
+
|
|
394
|
+
A fourth check concerns overrides, not profiles:
|
|
395
|
+
|
|
396
|
+
| ID | Severity | Subject | Condition |
|
|
397
|
+
| --- | --- | --- | --- |
|
|
398
|
+
| `skill_override_outdated` | warning | `skill:<name>` | The shipped skill's current fingerprint differs from the base recorded in `<override dir>/.pi-session-mcp-bases.json`. |
|
|
399
|
+
| `skill_override_outdated` | warning | `skill:bases` | The bases file is corrupt. |
|
|
400
|
+
|
|
401
|
+
It is `ok` for a recorded base that still matches. The remediation for a
|
|
402
|
+
changed skill names the command
|
|
403
|
+
`pi-session-mcp-setup --apply --customize-skill <name>`, after you reviewed the
|
|
404
|
+
change (see [Follow a changed shipped skill](#follow-a-changed-shipped-skill)).
|
|
405
|
+
Only skills with a recorded base are compared. Doctor reads the bases file and
|
|
406
|
+
the shipped files and executes nothing. A warning gives exit status `1`; it does
|
|
407
|
+
not block `setup`.
|
|
408
|
+
|
|
409
|
+
## Three states, and a fourth thing
|
|
410
|
+
|
|
411
|
+
Keep these apart:
|
|
412
|
+
|
|
413
|
+
1. **Configured.** `pi_capabilities_get` lists the alias under the profile's
|
|
414
|
+
`skills`. This is configuration intent only. It says nothing about the file.
|
|
415
|
+
2. **Available in the SDK catalog.** The skill passed validation at session
|
|
416
|
+
start and Pi lists it to the model in the system prompt.
|
|
417
|
+
3. **Actually read by the model.** The model decides to read the `SKILL.md`
|
|
418
|
+
with its `read` tool. This is not guaranteed.
|
|
419
|
+
|
|
420
|
+
Task success is separate from all three. A skill that the model read can still
|
|
421
|
+
produce a bad result, and a task can succeed without the skill.
|
|
422
|
+
|
|
423
|
+
## Snapshot semantics
|
|
424
|
+
|
|
425
|
+
The profile and its skill selection are fixed per session. The skill content
|
|
426
|
+
is not snapshotted: the SDK keeps file paths, and the model's later reads may
|
|
427
|
+
see changed files. This also applies to companion files that a skill refers
|
|
428
|
+
to.
|
|
429
|
+
|
|
430
|
+
- Manage skill files and companion files as operator content. Do not change
|
|
431
|
+
them while sessions that use them are active.
|
|
432
|
+
- Close the affected sessions before an update. New sessions then load the new
|
|
433
|
+
content.
|
|
434
|
+
- The configuration fingerprint covers the configuration bytes, not skill
|
|
435
|
+
contents.
|
|
436
|
+
- There is no hot reload, no watcher, no copy store for sessions and no
|
|
437
|
+
versioning. A change
|
|
438
|
+
to `skillCatalog` or `skills` needs a new server process like any other
|
|
439
|
+
configuration change. So does adding or removing an override of a library
|
|
440
|
+
skill, because `builtin:` is resolved when the configuration loads. Editing
|
|
441
|
+
the file of an override that already resolves needs no restart for new
|
|
442
|
+
sessions.
|
|
443
|
+
|
|
444
|
+
## Trust and limits
|
|
445
|
+
|
|
446
|
+
Skills are operator-managed prompt content. The override directory and its
|
|
447
|
+
bases file are operator-trusted configuration next to the configuration file,
|
|
448
|
+
never a workspace; keep them out of every workspace and writable only by you.
|
|
449
|
+
Setup copies the effective orchestration skill into the clients' skill
|
|
450
|
+
directories, where it becomes instructions for the controlling agent, so review
|
|
451
|
+
an override like code. In a `coding` profile a skill's
|
|
452
|
+
instructions are executed with that profile's tools, so review a skill like
|
|
453
|
+
code. A skill grants no rights: the tools of the permission profile stay the
|
|
454
|
+
limit.
|
|
455
|
+
|
|
456
|
+
Skill selection limits the regular skill catalog only. An allowlisted
|
|
457
|
+
extension remains trusted executable code. It can still read files or inject
|
|
458
|
+
prompt text. This is not a sandbox.
|
|
459
|
+
|
|
460
|
+
No MCP tool and no tool argument takes a skill. `pi_session_start` and
|
|
461
|
+
`pi_session_prompt` are unchanged.
|
|
462
|
+
|
|
463
|
+
Pi lists each available skill to the model with the absolute path of its
|
|
464
|
+
`SKILL.md`, so that the model can read it. The model may repeat that path in
|
|
465
|
+
its answer. Capabilities, errors and diagnostics stay path-free, but completed
|
|
466
|
+
`assistantText` is model output and is not sanitized.
|
|
467
|
+
|
|
468
|
+
## Migration: profiles that relied on package skills
|
|
469
|
+
|
|
470
|
+
With Pi SDK 1.1.0, an allowlisted extension package's bundled skills reached
|
|
471
|
+
the session although `noSkills` was set. The same held for prompt
|
|
472
|
+
templates and themes that a package shipped. Now an extension allowlist alone
|
|
473
|
+
makes none of its skills available. Prompt templates and themes that packages
|
|
474
|
+
ship are closed as well, through the SDK's public overrides. They were never
|
|
475
|
+
expanded for MCP prompts. Profiles without extensions are not affected.
|
|
476
|
+
|
|
477
|
+
If a profile used a skill that a package shipped:
|
|
478
|
+
|
|
479
|
+
1. Find the package's `SKILL.md` inside Pi's install, normally
|
|
480
|
+
`<Pi agent dir>/npm/node_modules/<package>/…`.
|
|
481
|
+
2. Add a catalog entry with the absolute path of that file. `~` is not
|
|
482
|
+
expanded.
|
|
483
|
+
3. Select the alias in the profile's `skills`.
|
|
484
|
+
4. Run Doctor and start a session to confirm.
|
|
485
|
+
|
|
486
|
+
Keep in mind that a package update can move or change the file. The catalog
|
|
487
|
+
path then needs a check.
|
package/docs/threat-model.md
CHANGED
|
@@ -26,6 +26,14 @@ Pi Session MCP trusts the local process that launches and speaks MCP over inheri
|
|
|
26
26
|
`process.execPath`, `dist/`, and `PI_SESSION_MCP_CONFIG`; no arbitrary `cwd` is
|
|
27
27
|
accepted. Durable pending/owned ownership state contains neither paths nor
|
|
28
28
|
secrets.
|
|
29
|
+
- **Skill installation into clients:** `setup --apply` writes the controller skill `pi-session-orchestration` into the clients' skill directories, in the home directory (`~/.agents/skills`, `~/.claude/skills`) and, for Claude Code `project`, in the project that setup runs in (`<project>/.claude/skills`). What is written there becomes instructions for the controlling agent, so the copy is as trusted as the package or the override it comes from. Mitigations:
|
|
30
|
+
- Copies come only from the package's `skills/` directory or from the operator's override directory next to the configuration file. No tool argument, client prompt or workspace names a source.
|
|
31
|
+
- The override directory and its `.pi-session-mcp-bases.json` are operator-trusted configuration next to the configuration file, never a workspace. Keep them out of every workspace and writable only by the operator; a `coding` session that can write there could change what setup installs next.
|
|
32
|
+
- Setup reads a bounded tree of regular files (at most 32 files and 1 MiB, no links or special files) and installs it as a real copy, never as a link. The copy is staged and renamed into place; only the exact old tree that setup itself moved is deleted afterwards.
|
|
33
|
+
- Setup never replaces or deletes a modified installed copy, hidden operator entries inside it, a foreign skill of the same name or a linked or non-directory entry; it reports `skill_divergent`. A link to exactly the effective skill is accepted as the operator's own (`skill_linked`) and never written through or deleted. Ownership records hold a content fingerprint (and, during an update, the replaced fingerprint), no path; a project record carries an unsalted, truncated SHA-256 of the project's real path as an opaque identity, which someone who can read the state file could test against guessed paths.
|
|
34
|
+
- A project may be untrusted. Inside a project setup never follows a link: any link below the project root makes the slot divergent, so a repository cannot redirect the write outside itself. In the home directory the client's skills directory may be the operator's own link (for example into a dotfiles checkout) and is followed; the skill entry itself is never followed.
|
|
35
|
+
- `--customize-skill` writes only below the override directory, never overwrites an existing override and never edits an operator's file. It moves the recorded base only on an explicit `--apply`, which acknowledges a reviewed change to the shipped skill.
|
|
36
|
+
- Worker skills are not installed into clients. Reports name the skill and a stable code, never a path or content.
|
|
29
37
|
- **False verification:** Verify combines Doctor and exact registration
|
|
30
38
|
equality with a bounded direct MCP initialize, `tools/list`, and
|
|
31
39
|
`pi_capabilities_get({})` call. It never starts a session or invokes
|
|
@@ -68,7 +76,7 @@ Pi Session MCP trusts the local process that launches and speaks MCP over inheri
|
|
|
68
76
|
- **Thinking-level clamping:** SDK capability handling can alter a requested level. The adapter compares the effective `session.thinkingLevel` after creation and disposes on a mismatch.
|
|
69
77
|
- **Orphaned SDK session:** a post-creation mismatch or later registry failure could otherwise leave a live Pi handle. The adapter holds it locally until all postconditions pass, best-effort disposes on each later failure, and the registry admits only verified handles.
|
|
70
78
|
- **Excess capability:** the execution profile selects a permission-derived tool allowlist. Read-only permits only `read`, `grep`, `find`, and `ls`; coding remains high impact.
|
|
71
|
-
- **Project resource code execution:** Pi resource loading disables extension discovery,
|
|
79
|
+
- **Project resource code execution:** Pi resource loading disables extension discovery, default skill directories, prompts, and themes; only a profile's allowlisted extensions and its explicitly selected catalog skills load (see below). A skill, prompt template or theme that an extension package ships is not made available by the allowlist. Non-executable `AGENTS.md` context remains untrusted instruction content, never authorization.
|
|
72
80
|
- **Concurrent state corruption:** a per-session queue serializes prompt admission and close; concurrent abort callers share one attempt for the active turn. Closing is terminal, settles an active turn, and disposes once.
|
|
73
81
|
- **Secret/prompt disclosure:** stdout is protocol-only. Stderr diagnostics use stable code and safe context only. Public metadata is whitelisted and omits auth objects/sources, credential paths, headers, base URLs, complete model objects, SDK IDs, raw provider errors, prompts, transcripts, and tool data. Completed `assistantText` can still repeat model-visible data and is potentially sensitive.
|
|
74
82
|
- **Capability-enumeration disclosure:** the trusted local MCP peer can read configured workspace aliases and execution-profile provider/model intent. Discovery omits workspace paths, authentication state, SDK state, sessions, turns, prompts, transcripts, and tool data. Operators must choose aliases that are suitable for this trusted-peer boundary.
|
|
@@ -80,6 +88,15 @@ Pi Session MCP trusts the local process that launches and speaks MCP over inheri
|
|
|
80
88
|
- `read-only` profiles never activate extension tools. At session start, after load and again after binding, no extension tool may shadow a built-in or granted tool; later registrations are covered in the residual risks.
|
|
81
89
|
- Client prompts never dispatch extension commands, but extension input hooks can still see, rewrite or consume a prompt. They receive it with `source: "rpc"`, Pi's marker for input from a program, so a hook that reads the source sees that no human typed it. A hook that ignores the source treats it like any other input.
|
|
82
90
|
- Each extension session gets its own model runtime, and close emits `session_shutdown`.
|
|
91
|
+
- **Skills as prompt content:** a profile's `skills` select files from the operator's `skillCatalog`. The MCP client cannot name a skill, a path or a catalog entry; `pi_session_start` and `pi_session_prompt` take no skill input. Mitigations:
|
|
92
|
+
- Catalog values are single local `SKILL.md` files: no directories, globs, URLs, scheme-prefixed sources, `~` or backslashes. The one accepted scheme is `builtin:<name>`, which resolves to the operator's override next to the configuration file or else to the skill shipped in the package, and to no other place. Relative paths resolve against the configuration file's directory, never against a workspace.
|
|
93
|
+
- The server loads exactly the selected files with no default directories, validates them at session start and rejects oversized (over 256 KiB), duplicate, invalid and explicit-only skills with `skill_load_failed`. Its message and diagnostics never contain a path, skill name or SDK text.
|
|
94
|
+
- Selection limits the regular skill catalog only. An allowlisted extension stays trusted executable code and can still read files or inject prompt text.
|
|
95
|
+
- Skills are operator-managed prompt content. In `coding` profiles a skill's instructions run with the profile's tools, so a skill grants no rights but can direct everything the profile may do. Review skills like code.
|
|
96
|
+
- Content is not snapshotted: the SDK keeps file paths, so a changed skill or companion file can reach a running session. Operators must not change them during active sessions. The configuration fingerprint covers configuration bytes, not skill contents.
|
|
97
|
+
- A `coding` session can write any file in its workspace, including a catalog file that lies inside it, and so change the instructions of other sessions and profiles. Operators keep catalog files outside every configured workspace; nothing enforces this.
|
|
98
|
+
- Whether the model reads a listed skill is the model's decision; configured, available and actually read are different states.
|
|
99
|
+
- Pi lists each available skill to the model with the absolute path of its `SKILL.md`, so the model knows that path and can repeat it in `assistantText`. Capabilities, errors and diagnostics stay path-free; completed `assistantText` is model output and not sanitized.
|
|
83
100
|
- **stdout corruption:** every write through `process.stdout` or `console.log`, `console.info` and `console.debug` other than the MCP transport's is dropped. The stdout guard intercepts `process.stdout.write`, `process.stdout.end` and `console.log`, `console.info` and `console.debug`, which covers output from extensions and the SDK in the server process. stderr gets only `foreign_stdout_suppressed` with byte and write counts, never the content. Anything that writes file descriptor 1 directly is not covered; see the residual risks.
|
|
84
101
|
- **Misleading annotations:** annotations are client hints only and never grant access.
|
|
85
102
|
- **Shutdown orphaning:** `SIGINT`, `SIGTERM`, and stdin EOF invoke the same bounded registry cleanup and transport close, so a client that only closes stdin does not leave sessions or their MCP children running. Handles are disposed at most once; late promises are ignored after removal. Explicit process exit prevents local shutdown from hanging indefinitely, but SDK limitations can leave external work unconfirmed or abruptly cut off.
|
|
@@ -104,7 +121,7 @@ sanitizing catch. A foreign transport exception with identical text remains
|
|
|
104
121
|
generic. This does not raise the limit, permit additional remote error codes or
|
|
105
122
|
change public terminal errors; cancellation and close still take precedence.
|
|
106
123
|
|
|
107
|
-
Aliases
|
|
124
|
+
Aliases, profile definitions, skill catalog entries and the skill override directory are trusted administrator configuration, not a filesystem or provider-security sandbox. A locally available model may later be unreachable; no live provider request is made during selection. Symlinks and Pi tools can reach resources permitted to the OS identity. `AGENTS.md` can influence model behavior. The number of active sessions and the duration of an already accepted turn remain unbounded. Stdio peer authentication, quotas, persistent recovery, provider hard-kill capability, dependency integrity policy, and OS/filesystem isolation remain outside the verified boundary. Coding-profile acceptance checks behavior in a selected fixture; it does not prove OS-level isolation.
|
|
108
125
|
The trusted same-UID operator can unlink or replace the setup lock path between
|
|
109
126
|
checks and must not mutate the ownership directory during a transaction.
|
|
110
127
|
|
package/docs/tool-contracts.md
CHANGED
|
@@ -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.
|
|
25
|
+
"server": { "name": "pi-session-mcp", "version": "0.8.0" },
|
|
26
26
|
"configuration": {
|
|
27
27
|
"fingerprint": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
28
28
|
"reloadPolicy": "restart-required"
|
|
@@ -35,12 +35,13 @@ There are exactly eight tools. No `pi_turn_wait` tool or live provider/model inv
|
|
|
35
35
|
"provider": "configured-provider",
|
|
36
36
|
"model": "configured-model",
|
|
37
37
|
"thinkingLevel": "medium",
|
|
38
|
-
"extensions": []
|
|
38
|
+
"extensions": [],
|
|
39
|
+
"skills": []
|
|
39
40
|
}]
|
|
40
41
|
}
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
The server sorts both arrays by alias with a deterministic code-point comparison. It copies only loaded configuration fingerprint/reload policy, configured aliases, and the
|
|
44
|
+
The server sorts both arrays by alias with a deterministic code-point comparison. It copies only loaded configuration fingerprint/reload policy, configured aliases, and the eight documented profile fields. `extensions` lists the configured extension specs (`npm:<name>@<version>`), empty when a profile loads none; it makes no claim that the package is installed. `skills` lists the skill-catalog aliases that the profile selects, in configured order, `[]` when it selects none. It contains no paths, file names, contents or SDK diagnostics, and it is configuration intent only: it makes no claim that a skill file exists, loads, or will be read by the model. See [Pi skills](skills.md). It never copies the configuration path or contents, workspace paths, authentication state, SDK data, session/turn data, prompts, transcripts, or tool arguments/results. The handler reads the in-memory loaded snapshot only and does not call the registry, Pi adapter, provider, filesystem, or network. The fingerprint identifies the exact loaded bytes, not current-file freshness; provider/model fields describe configured intent and make no availability claim.
|
|
44
45
|
|
|
45
46
|
Annotations are `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, and `openWorldHint: false`. Clients may use them for presentation, but the strict input schema and server-owned projection enforce the contract.
|
|
46
47
|
|
|
@@ -52,6 +53,8 @@ The former `profile` input is rejected; it is not reinterpreted as an execution-
|
|
|
52
53
|
|
|
53
54
|
Successful session metadata is a whitelist: `id`, `workspace`, `executionProfile`, `profile`, `provider`, `model`, `thinkingLevel`, `state`, `createdAt`, and `updatedAt`. `profile` remains derived permission metadata (`read-only` or `coding`) for compatibility; it is not client-selectable. Provider, model, and thinking level are projected only after SDK post-verification.
|
|
54
55
|
|
|
56
|
+
The selected skills of an execution profile are never an input. A session loads exactly the skills that the profile selects from the operator's skill catalog, validated at start; a failure is `skill_load_failed`. A catalog value is the path of one `SKILL.md` or `builtin:<name>`, which names a skill of the skill library: the operator's override next to the configuration file if it exists, else the skill shipped in the package. It is resolved when the server loads the configuration, and the value never appears in tool output. See [Pi skills](skills.md).
|
|
57
|
+
|
|
55
58
|
## Deterministic MCP errors
|
|
56
59
|
|
|
57
60
|
Public MCP errors are stable and sanitized. Their messages do not include inputs, auth details, provider responses, filesystem paths, or secrets.
|
|
@@ -72,6 +75,7 @@ Public MCP errors are stable and sanitized. Their messages do not include inputs
|
|
|
72
75
|
| `extension_version_mismatch` | Pi's installed extension package has another version than the configured one. |
|
|
73
76
|
| `extension_load_failed` | A configured extension has an invalid manifest, failed to load or failed to bind. |
|
|
74
77
|
| `extension_tool_conflict` | An extension tool name collides with a built-in, MCP or other extension tool, or is unsafe: not 1 to 64 letters, digits, `_` or `-` (not starting with `-`), or reserved for MCP (`mcp__` prefix, `list_mcp_resources`, `list_mcp_resource_templates`, `read_mcp_resource`). |
|
|
78
|
+
| `skill_load_failed` | A skill that the profile selects could not be loaded: a missing (also a `builtin:` name that matches no override and no shipped skill), unreadable or oversized (over 256 KiB) file, an invalid skill, two selected files with the same Pi skill name, two aliases on the same canonical file, or a skill with `disable-model-invocation: true`. The message is the fixed `Configured Pi skill could not be loaded`; it never contains a path, skill name or SDK text. |
|
|
75
79
|
| `pi_session_creation_failed` | Pi session construction failed without a more specific safe classification. |
|
|
76
80
|
| `server_stopping` | Shutdown has begun, so a new session cannot be admitted. |
|
|
77
81
|
|
|
@@ -81,7 +85,7 @@ Invalid execution-profile configuration prevents startup, so it cannot be an MCP
|
|
|
81
85
|
|
|
82
86
|
| Startup diagnostic code | Meaning |
|
|
83
87
|
| --- | --- |
|
|
84
|
-
| `invalid_execution_profile_config` | The execution-profile configuration violates its invariants or strict shape. |
|
|
88
|
+
| `invalid_execution_profile_config` | The execution-profile configuration violates its invariants or strict shape, including an unknown or duplicate selected skill alias, two selected skill aliases with the same path, or an invalid `skillCatalog` entry (including a malformed `builtin:` name). |
|
|
85
89
|
| `invalid_thinking_level` | A configured thinking level is outside the supported enum. |
|
|
86
90
|
|
|
87
91
|
`pi_session_prompt` returns `{session,turn}` only after successful Pi preflight. Preflight is bounded at 5,000 ms; a missing callback, hanging prompt acceptance, or timeout returns `prompt_timeout` / `Pi prompt preflight timed out` and creates no public turn. Late settlement may only release the unpublished operation's quarantine; it cannot publish a turn. `pi_session_abort` waits at most 5,000 ms per caller for one shared SDK abort attempt and returns `abort_timeout` / `Pi abort timed out` without claiming the turn was aborted. Rejection/failure remain `prompt_rejected`/`abort_failed`. Close allows at most 5,000 ms for abort cleanup, then performs best-effort disposal and removes the public registry entry; it remains idempotent through the retained tombstone. Registry shutdown rejects new starts, allows 12,000 ms, and disposes a handle from a late-resolving start instead of admitting it. Process shutdown, started by `SIGINT`, `SIGTERM`, or stdin EOF, allows 15,000 ms, attempts transport cleanup even after registry failure/timeout, then explicitly exits the process. These boundaries do not guarantee graceful cancellation of a provider request. `pi_turn_get` returns a `TurnView` with `turnId`, `sessionId`, state, timestamps, and `completedAt` for terminal turns. Completed views add normalized final `assistantText` and `truncated`; failed views contain only `{code:"turn_failed",message:"Pi turn failed"}`. Final assistant text is capped at 64 KiB UTF-8 bytes, each active session retains at most 20 turns, and close removes its turn data.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-session-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Local stdio MCP server for controlled Pi coding-agent sessions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
".pi-session-mcp-cli/",
|
|
30
30
|
"scripts/doctor.mjs",
|
|
31
31
|
"pi-session-mcp.example.json",
|
|
32
|
+
"skills/",
|
|
32
33
|
"docs/",
|
|
33
34
|
"!docs/superpowers/",
|
|
34
35
|
"CHANGELOG.md",
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"workspaces": {
|
|
3
|
-
"project": "
|
|
3
|
+
"project": "/absolute/path/to/project"
|
|
4
|
+
},
|
|
5
|
+
"skillCatalog": {
|
|
6
|
+
"pi-session-implementation": "builtin:pi-session-implementation",
|
|
7
|
+
"pi-session-review": "builtin:pi-session-review"
|
|
4
8
|
},
|
|
5
9
|
"executionProfiles": {
|
|
6
10
|
"safe-readonly": {
|
|
@@ -8,14 +12,16 @@
|
|
|
8
12
|
"permissionProfile": "read-only",
|
|
9
13
|
"provider": "example-provider",
|
|
10
14
|
"model": "example-model",
|
|
11
|
-
"thinkingLevel": "medium"
|
|
15
|
+
"thinkingLevel": "medium",
|
|
16
|
+
"skills": ["pi-session-review"]
|
|
12
17
|
},
|
|
13
18
|
"coding-example": {
|
|
14
19
|
"default": false,
|
|
15
20
|
"permissionProfile": "coding",
|
|
16
21
|
"provider": "another-example-provider",
|
|
17
22
|
"model": "another-example-model",
|
|
18
|
-
"thinkingLevel": "high"
|
|
23
|
+
"thinkingLevel": "high",
|
|
24
|
+
"skills": ["pi-session-implementation"]
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
27
|
}
|