@ikuma.cloud/pix-mcp 0.0.8 → 0.0.10

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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @ikuma.cloud/pix-mcp
2
2
 
3
3
  A small Pi MCP adapter: discover tools, load their schemas on demand, call
4
- those tools natively, and run user-selected MCP prompts. No scripting engine or
5
- model-provider-specific API is required.
4
+ those tools natively, and use user-selected MCP prompts and resources. No
5
+ scripting engine or model-provider-specific API is required.
6
6
 
7
7
  ## Usage
8
8
 
@@ -13,34 +13,60 @@ pi -e /absolute/path/to/pix/packages/pix-mcp
13
13
  ```
14
14
 
15
15
  Disable any other MCP adapter that would collide with the `mcp` tool,
16
- `/mcp-prompt` command, or flags, but keep any permission-control extensions
17
- enabled. Review the configuration and automatic startup behavior below before
18
- connecting servers.
16
+ `/mcp-prompt` or `/mcp-resource` commands, or flags, but keep any
17
+ permission-control extensions enabled. Review the configuration and automatic
18
+ startup behavior below before connecting servers.
19
+
20
+ From this repository, the included configuration launches the pinned MCP
21
+ Everything server for manual prompt and resource testing:
22
+
23
+ ```sh
24
+ mise run mcp:dev --mcp-config pix-mcp-test.json
25
+ ```
26
+
27
+ Review the file first; `npx` downloads and runs the pinned package.
19
28
 
20
29
  ## Configuration
21
30
 
22
- By default, read only `.mcp.json` in Pi's working directory. There is no ancestor
23
- search, global config merge, automatic import, or persistent metadata cache.
24
- Relative `--mcp-config` paths resolve from that working directory; a stdio
25
- server's `cwd` resolves from the config directory and defaults to that directory.
31
+ Without an explicit selection, the adapter reads these files in order:
26
32
 
27
- The adapter automatically loads the selected file and starts its enabled servers
28
- in all modes, without a confirmation prompt. Use `--mcp-config <path>` to select
29
- a different file.
33
+ 1. `<agent-dir>/mcp.json` for user-level servers. Pi's agent directory defaults
34
+ to `~/.pi/agent` and can be changed with `PI_CODING_AGENT_DIR`.
35
+ 2. `.mcp.json` in Pi's working directory for project-level servers.
30
36
 
31
- **Breaking change:** `--mcp-trust-config` has been removed. Remove it from existing
32
- launch commands; print and JSON sessions also load the default file automatically.
37
+ Missing files are ignored. Project declarations replace global declarations by
38
+ server name as complete entries; fields are not merged. A project entry with
39
+ `"disabled": true` masks the corresponding global server. An invalid project
40
+ entry also masks its global counterpart and reports the validation issue instead
41
+ of starting the global definition. Relative stdio `cwd` values resolve from the
42
+ file that declares the server and default to that file's directory. There is no
43
+ ancestor search, cross-client import, or persistent metadata cache.
44
+
45
+ Use `--mcp-config <path>` to read only that file for the session, without global
46
+ or project fallback. A relative explicit path resolves from Pi's working
47
+ directory. The adapter automatically starts every effective enabled server in all
48
+ modes without a confirmation prompt.
33
49
 
34
- Review the file before starting Pi: it can launch arbitrary local programs and
35
- contact remote services. A bare `.mcp.json` is not protected by Pi's project-trust
36
- mechanism, and the adapter is not an OS sandbox. Set a server's `disabled` field
37
- to `true` to prevent it from starting.
50
+ `getAgentDir()` cannot observe an `agentDir` supplied only through Pi 0.87's SDK
51
+ because extensions do not receive it. Embedded users should also set
52
+ `PI_CODING_AGENT_DIR` when they want the global file to follow an SDK override.
38
53
 
39
- At session startup, interactive and RPC sessions receive an `MCP config: <path>`
40
- notice with the resolved absolute path after the file is read. The notice
41
- identifies the configuration file, not whether every server connected; it never
42
- includes configuration contents. Missing, unreadable, or malformed files produce
43
- no notice. Print and JSON sessions remain silent.
54
+ **Breaking change:** `--mcp-trust-config` has been removed. Remove it from existing
55
+ launch commands; print and JSON sessions also load the default files
56
+ automatically.
57
+
58
+ Review both files before starting Pi: they can launch arbitrary local programs
59
+ and contact remote services. Global servers start in every working directory. A
60
+ bare project `.mcp.json` is not protected by Pi's project-trust mechanism, and
61
+ the adapter is not an OS sandbox. Set a server's `disabled` field to `true` to
62
+ prevent it from starting.
63
+
64
+ At session startup, interactive and RPC sessions display every successfully
65
+ loaded file as `MCP config (<scope>): <absolute-path>`, in precedence order. They
66
+ display `MCP config: none found` when no applicable file exists, or a path-only
67
+ error notice when a file fails to load. These notices occur before server startup
68
+ and never include configuration contents or indicate that every server connected.
69
+ Print and JSON sessions remain silent.
44
70
 
45
71
  ```json
46
72
  {
@@ -83,7 +109,7 @@ URLs, and HTTP headers.
83
109
  | `type` | `stdio`, `http`, or `streamable-http` (alias of `http`); only stdio is inferred, when `command` is present |
84
110
  | `command`, `args`, `env` | Stdio only; executable and argument array, not a shell command |
85
111
  | `url`, `headers` | Streamable HTTP only; explicit `type` required; no legacy SSE fallback or redirect following |
86
- | `timeout` | Hard deadline for each tool invocation or prompt retrieval, in milliseconds; default 30000 |
112
+ | `timeout` | Hard deadline for each tool invocation, prompt retrieval, or resource read, in milliseconds; default 30000 |
87
113
  | `cwd` | Stdio extension: working directory relative to the config directory |
88
114
  | `description` | Discovery extension: optional summary, truncated to 500 characters |
89
115
  | `startupTimeoutMs` | pix extension: complete connection/initialization handshake deadline; default 30000 |
@@ -101,15 +127,17 @@ Unknown fields invalidate their server entry rather than being silently ignored.
101
127
 
102
128
  ### Configuration errors
103
129
 
104
- An invalid server entry is skipped without hiding healthy servers. Discovery's
105
- `servers` list includes a safe diagnostic for each skipped entry; a valid server
106
- name can still be used with `mcp({ action: "list", server: "name" })` to inspect
130
+ An invalid server entry is skipped without hiding unrelated healthy servers.
131
+ Discovery's `servers` list includes a safe diagnostic for each skipped entry; a
132
+ valid server name can still be used with `mcp({ action: "list", server: "name" })` to inspect
107
133
  its status. Invalid names are replaced with their one-based entry positions.
108
134
  Diagnostics identify supported fields or migration steps without echoing URLs,
109
135
  commands, headers, argument values, or environment-variable names.
110
136
 
111
137
  Malformed JSON, invalid root structure, unknown root fields, and the file/server
112
- count limits remain fatal for the whole file. An invalid-only configuration
138
+ count limits remain fatal. A fatal error in either default file prevents servers
139
+ from the other file from starting. Each file may declare at most 32 entries, and
140
+ the merged result may enable at most 32 servers. An invalid-only configuration
113
141
  reports that no valid servers remain. Disabled entries are omitted, not reported
114
142
  as failed connections. Correct the file and reload Pi to retry.
115
143
 
@@ -117,9 +145,9 @@ as failed connections. Correct the file and reload Pi to retry.
117
145
 
118
146
  All three deadline fields accept integers from 1 through 2,147,483,647 milliseconds
119
147
  (Node's timer-safe maximum). Each defaults independently to 30 seconds. Setting
120
- `"timeout": 960000` permits a 16-minute tool call or prompt retrieval without
121
- lengthening startup or discovery. The invocation clock starts after connection
122
- startup; progress does not reset it. Catalog deadlines cover all pages of one
148
+ `"timeout": 960000` permits a 16-minute tool call, prompt retrieval, or resource
149
+ read without lengthening startup or discovery. The invocation clock starts after
150
+ connection startup; progress does not reset it. Catalog deadlines cover all pages of one
123
151
  snapshot; a subsequent list-change refresh starts a new deadline.
124
152
 
125
153
  HTTP deadlines cover response headers and bodies, including JSON and SSE. MCP
@@ -130,8 +158,9 @@ Upstream proxies and servers may still impose their own limits.
130
158
 
131
159
  **Breaking changes from 0.0.1:**
132
160
 
133
- - Replace `timeoutMs` with `timeout` for tool calls. Set `startupTimeoutMs` and
134
- `catalogTimeoutMs` separately if their defaults are unsuitable. The removed
161
+ - Replace `timeoutMs` with `timeout` for tool calls, prompt retrievals, and
162
+ resource reads. Set `startupTimeoutMs` and `catalogTimeoutMs` separately if
163
+ their defaults are unsuitable. The removed
135
164
  field produces a migration diagnostic; it is not an alias.
136
165
  - Add `"type": "http"` to remote entries that previously specified only `url`.
137
166
  - Connection strings now expand environment references beyond `env` and `headers`.
@@ -159,10 +188,9 @@ credentials; debug a failing server separately in a trusted environment.
159
188
  ## Discovery and execution
160
189
 
161
190
  At session startup, the adapter connects to enabled servers and fetches their
162
- advertised paginated tool and prompt catalogs. A server's configuration,
163
- connection, or discovery failure does not hide healthy features from other
164
- servers.
165
- Full schemas stay out of model context until selected. **Schema exposure is lazy;
191
+ advertised paginated tool, prompt, resource, and resource-template catalogs. A
192
+ server's configuration, connection, or discovery failure does not hide healthy
193
+ features from other servers. Full schemas stay out of model context until selected. **Schema exposure is lazy;
166
194
  initial connections and metadata discovery are not.**
167
195
 
168
196
  The agent uses the `mcp` tool:
@@ -198,8 +226,8 @@ exceptions, schema contents, invalid tool names, and dialect URLs are not expose
198
226
 
199
227
  An unsupported output schema still fails that server's tool discovery rather than
200
228
  producing a per-tool rejection. Losing an established HTTP notification stream
201
- withdraws tool and prompt catalogs rather than silently keeping stale metadata;
202
- servers that decline the optional stream with HTTP 405 remain usable. Reload Pi
229
+ withdraws tool, prompt, and resource catalogs rather than silently keeping stale
230
+ metadata; servers that decline the optional stream with HTTP 405 remain usable. Reload Pi
203
231
  to reconnect a failed server or reread configuration.
204
232
 
205
233
  Pi handles provider compatibility. Some providers support transcript-anchored
@@ -282,12 +310,12 @@ every mode; `run` submits immediately and can pass an intentional empty value as
282
310
  `name=`.
283
311
 
284
312
  Arguments use shell-style quoting. Positional values map to the prompt's declared
285
- argument order; `name=value` selects a declared argument explicitly. Quote or escape
286
- an equals sign in a positional value (for example, `"a=b"` or `a\=b`) to avoid
287
- assignment parsing. Argument names containing `=` work when the name is quoted,
313
+ argument order; `name=value` selects a declared argument explicitly. Quote or
314
+ escape an equals sign in a positional value (for example, `"a=b"` or `a\=b`) to
315
+ avoid assignment parsing. Argument names containing `=` work when the name is quoted,
288
316
  as in `"x=y"=value`. The adapter checks required arguments before sending
289
- `prompts/get`. Prompt retrieval uses the
290
- server's `timeout`; prompt discovery uses `catalogTimeoutMs` and follows pagination.
317
+ `prompts/get`. Prompt retrieval uses the server's `timeout`; prompt discovery uses
318
+ `catalogTimeoutMs` and follows pagination.
291
319
  Prompt list-change notifications atomically replace that server's prompt catalog.
292
320
  Duplicate or invalid prompt metadata fails only that server's prompt catalog. A
293
321
  prompt discovery failure does not hide healthy tools, and a tool discovery failure
@@ -305,6 +333,60 @@ Prompt metadata and bodies are untrusted server content. Catalog metadata stays
305
333
  in command UI; a prompt body enters model context only after the user explicitly
306
334
  runs it. Review configured servers and selected prompts accordingly.
307
335
 
336
+ ## Resources
337
+
338
+ MCP resources are application-controlled and are not exposed as model-callable
339
+ tools. Use the stable `/mcp-resource` command:
340
+
341
+ ```text
342
+ /mcp-resource
343
+ /mcp-resource list [server]
344
+ /mcp-resource read <server> <uri-or-template> [name=value ...]
345
+ ```
346
+
347
+ In TUI mode, the bare command opens a native selector for direct resources and
348
+ resource templates. Focusing an item shows its bounded metadata but does not read
349
+ it. Selecting a template requests every variable in declaration order and expands
350
+ it according to [RFC 6570 Level 4](https://www.rfc-editor.org/rfc/rfc6570).
351
+ Escape cancels without reading. The result is placed in Pi's editor for review;
352
+ image contents use private temporary `@` references that are removed at session
353
+ shutdown.
354
+
355
+ The explicit `list` and `read` forms work in every mode. `read` immediately sends
356
+ the resource contents as a user message and starts or queues a model turn; Pi
357
+ commands do not provide a raw structured-result channel. A concrete URI need not
358
+ appear in the catalog, allowing known or optional-template URIs to be read
359
+ explicitly. Arguments are accepted only when the target exactly matches a
360
+ cataloged template. Template variables use the same shell-style positional and
361
+ `name=value` syntax as prompt arguments. MCP does not mark template variables as
362
+ required: omitted variables use RFC 6570's undefined-variable behavior, leaving a
363
+ picker input empty omits it, and explicit `name=` supplies an intentional empty
364
+ value. The expanded result must still be a valid absolute URI. MCP completion
365
+ requests for variable values are not supported.
366
+
367
+ Each returned content item gets a server/URI source marker because one read can
368
+ return multiple resources. Text and supported images are retained in order.
369
+ Non-image blobs and oversized or unsupported content are omitted from the preview
370
+ and preserved in the private full-result artifact. Unsafe terminal and
371
+ bidirectional controls are removed from displayed or editable text; the original
372
+ content remains in the artifact when sanitization changes it, while `_meta` is
373
+ excluded.
374
+
375
+ Direct resources and templates are discovered independently from tools and
376
+ prompts, but committed together as one atomic per-server resource snapshot.
377
+ Resource list-change notifications refresh both catalogs. Duplicate, malformed,
378
+ or oversized metadata fails only that server's resource catalog. Picker
379
+ selections are rejected if any catalog refresh replaces the selected entry while
380
+ variables are being collected, content is being read or formatted, or the editor
381
+ is being updated.
382
+
383
+ Resource metadata, URIs, template values, and bodies are untrusted server content.
384
+ Icons are neither displayed nor fetched, `_meta` is not retained or included in
385
+ resource artifacts, and URIs containing userinfo credentials are rejected. A body
386
+ enters model context only after an explicit user selection or `read` command. Resource subscriptions
387
+ and update notifications are not supported, and resources are never reread or
388
+ injected automatically.
389
+
308
390
  ## Output and limits
309
391
 
310
392
  Text, supported images, and structured content are retained. Long text gets a
@@ -314,22 +396,31 @@ content is explicitly omitted from the preview, not silently discarded. Pi's
314
396
  error-result path is text-only, so images in MCP errors are preserved in a
315
397
  full-result artifact rather than displayed inline.
316
398
 
317
- When necessary, the full MCP tool or prompt result is written to
399
+ When necessary, the full MCP tool, prompt, or resource result is written to
318
400
  `pix-mcp-*/result.json` under the system temp directory (directory mode 0700,
319
- file mode 0600). Pi can inspect it with `read`. These artifacts may contain
320
- sensitive data and are **not deleted at session shutdown**; remove them when no
401
+ file mode 0600). Pi can inspect it with `read`; resource artifacts omit `_meta`.
402
+ These artifacts may contain sensitive data and are **not deleted at session
403
+ shutdown**; remove them when no
321
404
  longer needed. Output limits are not a complete memory or security sandbox.
322
405
 
323
- Configuration is limited to 256 KiB and 32 servers. Startup connects at most four
324
- servers concurrently. Each tool or prompt catalog is limited to 1000 entries,
325
- 100 pagination cursors, and 2 MiB of metadata; individual input/output schemas are
326
- limited to 64 KiB. Prompt arguments are limited to 256 KiB per retrieval;
327
- prompt and prompt-argument names are limited to 256 bytes, cannot contain Unicode
328
- control, format, or line-separator characters, and each prompt can declare at most
329
- 100 arguments. Tool names must use 1–128 ASCII letters, digits,
330
- underscores, hyphens, or periods. Tool and prompt descriptions, prompt-argument
331
- descriptions, and prompt titles are limited to 16 KiB. Stdio messages are limited
332
- to 16 MiB.
406
+ Each configuration file is limited to 256 KiB and 32 entries; the merged result
407
+ can enable at most 32 servers. Startup connects at most four servers concurrently.
408
+ Each tool or prompt catalog is limited to 1000 entries,
409
+ 100 pagination cursors, and 2 MiB of metadata. Direct resources and templates
410
+ share a 1000-entry and 2 MiB limit, with up to 100 cursors for each endpoint.
411
+ Individual input/output schemas are limited to 64 KiB. Prompt arguments and
412
+ resource-template arguments are limited to 256 KiB per retrieval; prompt and
413
+ prompt-argument names are limited to 256 bytes, cannot contain Unicode control,
414
+ format, or line-separator characters, and each prompt can declare at most 100
415
+ arguments. Tool names must use 1–128 ASCII letters, digits, underscores, hyphens,
416
+ or periods. Tool and prompt descriptions, prompt-argument descriptions, and
417
+ prompt titles are limited to 16 KiB. Resource URIs, templates, names, titles, and
418
+ descriptions are limited to 16 KiB; MIME types and template-variable names are
419
+ limited to 256 bytes; templates may contain at most 100 unique variables, and
420
+ resource annotations may contain at most two audience hints. A resource read may
421
+ return at most 100 content items and 16 MiB of serialized data.
422
+ Stdio messages are limited to 16 MiB. HTTP JSON responses and individual SSE
423
+ events are streaming-limited to 16 MiB plus 64 KiB of protocol framing.
333
424
  Schemas are syntax-checked before compilation; see [schema compatibility](#schema-compatibility)
334
425
  for supported dialects and the draft-07 subset. Schema nesting is limited to 64
335
426
  levels, including literal data. External schema references are unsupported, but
@@ -340,16 +431,16 @@ The adapter never automatically retries `tools/call`: a timeout or lost response
340
431
  may occur after a mutating operation took effect. Cancellation or expiration
341
432
  aborts only the affected HTTP request and sends a best-effort MCP cancellation
342
433
  notification; concurrent sibling calls remain usable. Successful output is
343
- validated against the schema captured when the call began; MCP error results are exempt
344
- from that success schema. Cancellation is best-effort at the server and does not
434
+ validated against the schema captured when the call began; MCP error results are
435
+ exempt from that success schema. Cancellation is best-effort at the server and does not
345
436
  roll back effects.
346
437
 
347
438
  ## Deliberately out of scope
348
439
 
349
- OAuth, legacy SSE transport, MCP resources APIs, prompt argument completion,
350
- sampling, elicitation, MCP apps, task execution, semantic search, scripting,
351
- config UI, and persistent catalog caching. Use a fuller adapter when those
352
- capabilities are required.
440
+ OAuth, legacy SSE transport, resource subscriptions, MCP prompt/resource
441
+ argument-value completion, sampling, elicitation, MCP apps, task execution,
442
+ semantic search, scripting, config UI, and persistent catalog caching. Use a
443
+ fuller adapter when those capabilities are required.
353
444
 
354
445
  ## Contributing
355
446
 
package/mcp.schema.json CHANGED
@@ -33,7 +33,7 @@
33
33
  "description": { "$ref": "#/$defs/text" },
34
34
  "timeout": {
35
35
  "$ref": "#/$defs/timeout",
36
- "description": "Hard deadline for one tool invocation or prompt retrieval."
36
+ "description": "Hard deadline for one tool invocation, prompt retrieval, or resource read."
37
37
  },
38
38
  "startupTimeoutMs": {
39
39
  "$ref": "#/$defs/timeout",
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@ikuma.cloud/pix-mcp",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "type": "module",
8
- "description": "MCP prompts and lazily activated native tools for Pi Coding Agent",
8
+ "description": "MCP resources, prompts, and lazily activated native tools for Pi Coding Agent",
9
9
  "keywords": [
10
10
  "pi-package"
11
11
  ],
@@ -22,7 +22,9 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@modelcontextprotocol/sdk": "1.30.0",
25
+ "@std-uritemplate/std-uritemplate": "2.0.12",
25
26
  "ajv": "8.20.0",
27
+ "fast-uri": "3.1.8",
26
28
  "undici": "8.10.2"
27
29
  },
28
30
  "peerDependencies": {