@cyanheads/pixoo-mcp-server 1.1.1 → 1.1.2

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/AGENTS.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** pixoo-mcp-server
4
- **Version:** 1.1.1
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
6
- **Engines:** Bun ≥1.3.0, Node ≥24.0.0
4
+ **Version:** 1.1.2
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.2`
6
+ **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revision 2026-07-28 alongside the 2025 era)
8
- **Zod:** ^4.4.3
8
+ **Zod:** ^4.6.4
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -28,13 +28,15 @@ Tools call renderer + service; they don't talk to the toolkit directly.
28
28
 
29
29
  When the user asks what's next or needs direction, suggest options based on the current project state. Common next steps:
30
30
 
31
- 1. **Re-run the `setup` skill** — ensures CLAUDE.md, skills, structure, and metadata are populated and up to date
32
- 2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-resource`, `add-prompt` skills
33
- 3. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill
34
- 4. **Run `devcheck`** — lint, format, typecheck, and security audit
35
- 5. **Run the `security-pass` skill** — audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation
36
- 6. **Run the `polish-docs-meta` skill** — finalize README, CHANGELOG, metadata, and agent protocol for shipping
37
- 7. **Run the `maintenance` skill** — investigate changelogs, adopt upstream changes, and sync skills after `bun update --latest`
31
+ 1. **Re-run the `setup` skill** — ensures CLAUDE.md, skills, structure, and metadata are populated and up to date with the current codebase
32
+ 2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-app-tool`, `add-resource`, `add-prompt` skills
33
+ 3. **Add services** — scaffold domain service integrations using the `add-service` skill
34
+ 4. **Add tests** — scaffold tests for existing definitions using the `add-test` skill
35
+ 5. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill, get a report of issues and pain points
36
+ 6. **Run `devcheck`** — lint, format, typecheck, and security audit
37
+ 7. **Run the `security-pass` skill** — audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation
38
+ 8. **Run the `polish-docs-meta` skill** — finalize README, CHANGELOG, metadata, and agent protocol for shipping
39
+ 9. **Run the `maintenance` skill** — investigate changelogs, adopt upstream changes, and sync skills after `bun update --latest`
38
40
 
39
41
  Tailor suggestions to what's actually missing or stale — don't recite the full list every time.
40
42
 
@@ -45,11 +47,12 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
45
47
  - **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `serviceUnavailable()`, etc.) when the error code matters.
46
48
  - **Use `ctx.log`** for request-scoped logging. No `console` calls.
47
49
  - **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
48
- - **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler. (`ctx.elicit` was removed in the SDK v2 migration.)
50
+ - **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler. (`ctx.elicit` was removed in the SDK v2 migration.) The server declares `sessionMode: 'stateless'` because no handler does this today — the first one that does changes it to `{ default: 'stateful', require: 'stateful' }` in `src/index.ts`, `.env.example`, the Dockerfile, and the README.
49
51
  - **Secrets in env vars only** — never hardcoded.
52
+ - **Cut noise.** Add only what earns its place: no speculative generality, no guards for states the framework already prevents (Zod-validated params, classified errors), no abstraction until a third caller proves it, no option nothing sets.
50
53
  - **Every `PixooResult` checked.** No fire-and-forget device calls. `pushed: true` means `error_code: 0` from the device.
51
54
  - **Adding an env var requires both files** — `server.json` (`environmentVariables[]`) and `manifest.json` (`mcp_config.env` + `user_config`). `bun run lint:packaging` verifies the names match.
52
- - **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped.
55
+ - **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped. The comment is for future readers — state the concrete changes, not the conversation that produced them.
53
56
 
54
57
  ---
55
58
 
@@ -138,6 +141,19 @@ export function getServerConfig() {
138
141
  }
139
142
  ```
140
143
 
144
+ ### Session posture and shutdown
145
+
146
+ ```ts
147
+ await createApp({
148
+ sessionMode: 'stateless',
149
+ setup(core) { initPixooService(core.config, core.storage); },
150
+ });
151
+ ```
152
+
153
+ `sessionMode` declares the HTTP session posture in `src/`. `MCP_SESSION_MODE` still wins whenever it carries a meaningful value (an empty string and an unsubstituted `${…}` placeholder read as unset and fall through to the option). Add `require: 'stateful'` when a tool asks the caller for input mid-handler via `ctx.requestInput`: startup then fails with a `ConfigurationError` rather than serving a mode in which a 2025-era client can never answer the prompt. Stdio is never refused.
154
+
155
+ `teardown(core)` is the `setup()` counterpart — release a watcher, socket, or non-`unref()`'d timer there. It runs after the transport stops and before the logger closes, on every shutdown path. This server passes none: `PixooService` opens a `fetch` per device command and holds no persistent handle. Add one if a service starts keeping a socket, watcher, or ref'd timer.
156
+
141
157
  ---
142
158
 
143
159
  ## Context
@@ -187,6 +203,8 @@ errors: [
187
203
  ],
188
204
  ```
189
205
 
206
+ Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring. A tool argument that fails the input schema reaches the client as `InvalidParams` (-32602) with `structuredContent.error` — assert that code, not `ValidationError`, in tests.
207
+
190
208
  ---
191
209
 
192
210
  ## Structure
@@ -199,16 +217,14 @@ src/
199
217
  services/
200
218
  pixoo/
201
219
  pixoo-service.ts # PixooService — toolkit wrapper, pacing, result mapping
202
- types.ts # Service types
203
220
  renderer/
204
221
  themes.ts # Theme + palette registry
205
222
  icons.ts # Icon registry (SVG path data by category)
206
- styled-text.ts # Gradient ramp + shadow + outline text engine
207
- layout.ts # Semantic positioning resolver
208
- effects.ts # Animation preset → keyframe compiler
209
- keyframes.ts # Keyframe interpolation (lerp numbers/colors, snap booleans)
223
+ text-engine.ts # Gradient ramp + shadow + outline text engine, overflow handling
224
+ scene-renderer.ts # Element vocabulary, layout resolver, frame rendering
225
+ keyframes.ts # Keyframe interpolation + animation preset compiler
210
226
  preview.ts # PNG/contact-sheet/GIF encoding
211
- elements/ # Per-type element renderers
227
+ remote-image.ts # https image fetch to a temp file for the toolkit loader
212
228
  mcp-server/
213
229
  tools/definitions/
214
230
  pixoo-display-text.tool.ts
@@ -224,7 +240,10 @@ src/
224
240
  pixoo-icons.resource.ts
225
241
  pixoo-design-guide.resource.ts
226
242
  tests/
243
+ index.session-mode.test.ts # Boots the entry point over HTTP, pins the declared session mode
227
244
  renderer/ # Pure renderer unit tests (no device)
245
+ resources/ # Resource handler tests
246
+ services/pixoo/ # PixooService tests with a fake client
228
247
  tools/ # Tool handler tests with mock context
229
248
  ```
230
249
 
@@ -243,7 +262,9 @@ tests/
243
262
 
244
263
  ## Skills
245
264
 
246
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches.
265
+ Skills are modular instructions in `framework-skills/` at the project root. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, and this server ships `.claude-plugin/` and `.codex-plugin/`, so a root `skills/` would hand these development skills to every agent that installs it.
266
+
267
+ **Agent skill directories:** `.claude/skills/` and `.agents/skills/` carry copies of `framework-skills/`. After framework updates, run the `maintenance` skill — Phase B re-syncs both.
247
268
 
248
269
  Available skills:
249
270
 
@@ -258,24 +279,25 @@ Available skills:
258
279
  | `add-service` | Scaffold a new service integration |
259
280
  | `add-test` | Scaffold test file for a tool, resource, or service |
260
281
  | `field-test` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
261
- | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface |
262
- | `security-pass` | Audit server for MCP-flavored security gaps |
263
- | `code-simplifier` | Post-session cleanup against `git diff` |
282
+ | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
283
+ | `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
284
+ | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
264
285
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
265
- | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag |
266
- | `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker |
286
+ | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
287
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
288
+ | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
267
289
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
268
- | `orchestrations` | Chain task skills into a gated multi-phase pipeline when sub-agents are available |
269
- | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping |
290
+ | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
291
+ | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
270
292
  | `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
271
293
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
272
294
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
273
- | `api-canvas` | DataCanvas: register tabular data, run SQL, export — Tier 3 opt-in |
295
+ | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
274
296
  | `api-config` | AppConfig, parseEnvConfig, env vars |
275
297
  | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
276
298
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
277
299
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
278
- | `api-mirror` | MirrorService: self-refreshing local SQLite/FTS5 mirror of a bulk dataset — Tier 3 opt-in |
300
+ | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
279
301
  | `api-services` | LLM, Speech, Graph services |
280
302
  | `api-telemetry` | OTel catalog: spans, metrics, completion logs, env config, cardinality rules |
281
303
  | `api-testing` | createMockContext, createFetchMock, runToolContract, test patterns |
@@ -294,9 +316,10 @@ Available skills:
294
316
  | `bun run rebuild` | Clean + build |
295
317
  | `bun run clean` | Remove build artifacts |
296
318
  | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
297
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Re-resolves the `^`-ranged framework pin — verify the lock afterwards |
319
+ | `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
320
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
298
321
  | `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
299
- | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity |
322
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, MCPB `user_config` wiring, plugin manifests, README version badge (run by devcheck) |
300
323
  | `bun run list-skills` | Print the skill registry |
301
324
  | `bun run tree` | Generate directory structure doc |
302
325
  | `bun run format` | Auto-fix formatting (safe fixes only) |
@@ -310,6 +333,24 @@ Available skills:
310
333
 
311
334
  ---
312
335
 
336
+ ## Bundling
337
+
338
+ `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies and strips dependency-shipped agent docs and platform-specific native bindings that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP deployments are unaffected.
339
+
340
+ `lint:packaging` verifies that `server.json` and `manifest.json` declare the same env var names, that every `manifest.json` `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.<key>}"` (the host substitutes nothing else), that an optional string option carries `"default": ""`, that no plugin manifest writes an empty `env` value, and that the README `Version-` badge matches `package.json`.
341
+
342
+ ---
343
+
344
+ ## Changelog
345
+
346
+ Directory-based, grouped by minor series via the `.x` semver-wildcard convention. Source of truth: `changelog/<major.minor>.x/<version>.md` — one file per release, shipped in the npm package. At release, author the per-version file with a concrete version and date, then run `bun run changelog:build` to regenerate the rollup. `changelog/template.md` is a **pristine format reference** — never edited or moved. `CHANGELOG.md` is a **navigation index** regenerated by `bun run changelog:build` — devcheck hard-fails on drift; never hand-edit it.
347
+
348
+ Each per-version file opens with YAML frontmatter: `summary` (required, ≤350 chars), optional `breaking: true` for changes consumers must act on, optional `security: true` only for a security fix in this server's own source (never a dependency CVE bump — those go under `## Dependencies`).
349
+
350
+ **Section order:** the Keep a Changelog sequence — Added, Changed, Deprecated, Removed, Fixed, Security — then `Dependencies` last. Include only sections with entries.
351
+
352
+ ---
353
+
313
354
  ## Checklist
314
355
 
315
356
  - [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()`)
@@ -321,4 +362,5 @@ Available skills:
321
362
  - [ ] Every device call goes through `PixooService`; every `PixooResult` checked
322
363
  - [ ] Renderer functions have no device dependency — testable without hardware
323
364
  - [ ] Env var added? Declared in BOTH `server.json` and `manifest.json` (`lint:packaging` enforces parity)
365
+ - [ ] `.codex-plugin/plugin.json` and `.claude-plugin/plugin.json` carry the `package.json` `version`; display fields use the unscoped repo name `pixoo-mcp-server`. A user-supplied variable goes in `env_vars` (`.codex-plugin/mcp.json`) or `userConfig` + `"${user_config.<option>}"` (`.claude-plugin/plugin.json`) — never `"KEY": ""` in `env`
324
366
  - [ ] `bun run devcheck` and `bun run test` pass
package/CLAUDE.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** pixoo-mcp-server
4
- **Version:** 1.1.1
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
6
- **Engines:** Bun ≥1.3.0, Node ≥24.0.0
4
+ **Version:** 1.1.2
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.2`
6
+ **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revision 2026-07-28 alongside the 2025 era)
8
- **Zod:** ^4.4.3
8
+ **Zod:** ^4.6.4
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -28,13 +28,15 @@ Tools call renderer + service; they don't talk to the toolkit directly.
28
28
 
29
29
  When the user asks what's next or needs direction, suggest options based on the current project state. Common next steps:
30
30
 
31
- 1. **Re-run the `setup` skill** — ensures CLAUDE.md, skills, structure, and metadata are populated and up to date
32
- 2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-resource`, `add-prompt` skills
33
- 3. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill
34
- 4. **Run `devcheck`** — lint, format, typecheck, and security audit
35
- 5. **Run the `security-pass` skill** — audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation
36
- 6. **Run the `polish-docs-meta` skill** — finalize README, CHANGELOG, metadata, and agent protocol for shipping
37
- 7. **Run the `maintenance` skill** — investigate changelogs, adopt upstream changes, and sync skills after `bun update --latest`
31
+ 1. **Re-run the `setup` skill** — ensures CLAUDE.md, skills, structure, and metadata are populated and up to date with the current codebase
32
+ 2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-app-tool`, `add-resource`, `add-prompt` skills
33
+ 3. **Add services** — scaffold domain service integrations using the `add-service` skill
34
+ 4. **Add tests** — scaffold tests for existing definitions using the `add-test` skill
35
+ 5. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill, get a report of issues and pain points
36
+ 6. **Run `devcheck`** — lint, format, typecheck, and security audit
37
+ 7. **Run the `security-pass` skill** — audit handlers for MCP-specific security gaps: output injection, scope blast radius, input sinks, tenant isolation
38
+ 8. **Run the `polish-docs-meta` skill** — finalize README, CHANGELOG, metadata, and agent protocol for shipping
39
+ 9. **Run the `maintenance` skill** — investigate changelogs, adopt upstream changes, and sync skills after `bun update --latest`
38
40
 
39
41
  Tailor suggestions to what's actually missing or stale — don't recite the full list every time.
40
42
 
@@ -45,11 +47,12 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
45
47
  - **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `serviceUnavailable()`, etc.) when the error code matters.
46
48
  - **Use `ctx.log`** for request-scoped logging. No `console` calls.
47
49
  - **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
48
- - **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler. (`ctx.elicit` was removed in the SDK v2 migration.)
50
+ - **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler. (`ctx.elicit` was removed in the SDK v2 migration.) The server declares `sessionMode: 'stateless'` because no handler does this today — the first one that does changes it to `{ default: 'stateful', require: 'stateful' }` in `src/index.ts`, `.env.example`, the Dockerfile, and the README.
49
51
  - **Secrets in env vars only** — never hardcoded.
52
+ - **Cut noise.** Add only what earns its place: no speculative generality, no guards for states the framework already prevents (Zod-validated params, classified errors), no abstraction until a third caller proves it, no option nothing sets.
50
53
  - **Every `PixooResult` checked.** No fire-and-forget device calls. `pushed: true` means `error_code: 0` from the device.
51
54
  - **Adding an env var requires both files** — `server.json` (`environmentVariables[]`) and `manifest.json` (`mcp_config.env` + `user_config`). `bun run lint:packaging` verifies the names match.
52
- - **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped.
55
+ - **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped. The comment is for future readers — state the concrete changes, not the conversation that produced them.
53
56
 
54
57
  ---
55
58
 
@@ -138,6 +141,19 @@ export function getServerConfig() {
138
141
  }
139
142
  ```
140
143
 
144
+ ### Session posture and shutdown
145
+
146
+ ```ts
147
+ await createApp({
148
+ sessionMode: 'stateless',
149
+ setup(core) { initPixooService(core.config, core.storage); },
150
+ });
151
+ ```
152
+
153
+ `sessionMode` declares the HTTP session posture in `src/`. `MCP_SESSION_MODE` still wins whenever it carries a meaningful value (an empty string and an unsubstituted `${…}` placeholder read as unset and fall through to the option). Add `require: 'stateful'` when a tool asks the caller for input mid-handler via `ctx.requestInput`: startup then fails with a `ConfigurationError` rather than serving a mode in which a 2025-era client can never answer the prompt. Stdio is never refused.
154
+
155
+ `teardown(core)` is the `setup()` counterpart — release a watcher, socket, or non-`unref()`'d timer there. It runs after the transport stops and before the logger closes, on every shutdown path. This server passes none: `PixooService` opens a `fetch` per device command and holds no persistent handle. Add one if a service starts keeping a socket, watcher, or ref'd timer.
156
+
141
157
  ---
142
158
 
143
159
  ## Context
@@ -187,6 +203,8 @@ errors: [
187
203
  ],
188
204
  ```
189
205
 
206
+ Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring. A tool argument that fails the input schema reaches the client as `InvalidParams` (-32602) with `structuredContent.error` — assert that code, not `ValidationError`, in tests.
207
+
190
208
  ---
191
209
 
192
210
  ## Structure
@@ -199,16 +217,14 @@ src/
199
217
  services/
200
218
  pixoo/
201
219
  pixoo-service.ts # PixooService — toolkit wrapper, pacing, result mapping
202
- types.ts # Service types
203
220
  renderer/
204
221
  themes.ts # Theme + palette registry
205
222
  icons.ts # Icon registry (SVG path data by category)
206
- styled-text.ts # Gradient ramp + shadow + outline text engine
207
- layout.ts # Semantic positioning resolver
208
- effects.ts # Animation preset → keyframe compiler
209
- keyframes.ts # Keyframe interpolation (lerp numbers/colors, snap booleans)
223
+ text-engine.ts # Gradient ramp + shadow + outline text engine, overflow handling
224
+ scene-renderer.ts # Element vocabulary, layout resolver, frame rendering
225
+ keyframes.ts # Keyframe interpolation + animation preset compiler
210
226
  preview.ts # PNG/contact-sheet/GIF encoding
211
- elements/ # Per-type element renderers
227
+ remote-image.ts # https image fetch to a temp file for the toolkit loader
212
228
  mcp-server/
213
229
  tools/definitions/
214
230
  pixoo-display-text.tool.ts
@@ -224,7 +240,10 @@ src/
224
240
  pixoo-icons.resource.ts
225
241
  pixoo-design-guide.resource.ts
226
242
  tests/
243
+ index.session-mode.test.ts # Boots the entry point over HTTP, pins the declared session mode
227
244
  renderer/ # Pure renderer unit tests (no device)
245
+ resources/ # Resource handler tests
246
+ services/pixoo/ # PixooService tests with a fake client
228
247
  tools/ # Tool handler tests with mock context
229
248
  ```
230
249
 
@@ -243,7 +262,9 @@ tests/
243
262
 
244
263
  ## Skills
245
264
 
246
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches.
265
+ Skills are modular instructions in `framework-skills/` at the project root. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, and this server ships `.claude-plugin/` and `.codex-plugin/`, so a root `skills/` would hand these development skills to every agent that installs it.
266
+
267
+ **Agent skill directories:** `.claude/skills/` and `.agents/skills/` carry copies of `framework-skills/`. After framework updates, run the `maintenance` skill — Phase B re-syncs both.
247
268
 
248
269
  Available skills:
249
270
 
@@ -258,24 +279,25 @@ Available skills:
258
279
  | `add-service` | Scaffold a new service integration |
259
280
  | `add-test` | Scaffold test file for a tool, resource, or service |
260
281
  | `field-test` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
261
- | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface |
262
- | `security-pass` | Audit server for MCP-flavored security gaps |
263
- | `code-simplifier` | Post-session cleanup against `git diff` |
282
+ | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
283
+ | `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
284
+ | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
264
285
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
265
- | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag |
266
- | `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker |
286
+ | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
287
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
288
+ | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
267
289
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
268
- | `orchestrations` | Chain task skills into a gated multi-phase pipeline when sub-agents are available |
269
- | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping |
290
+ | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
291
+ | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
270
292
  | `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
271
293
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
272
294
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
273
- | `api-canvas` | DataCanvas: register tabular data, run SQL, export — Tier 3 opt-in |
295
+ | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
274
296
  | `api-config` | AppConfig, parseEnvConfig, env vars |
275
297
  | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
276
298
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
277
299
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
278
- | `api-mirror` | MirrorService: self-refreshing local SQLite/FTS5 mirror of a bulk dataset — Tier 3 opt-in |
300
+ | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
279
301
  | `api-services` | LLM, Speech, Graph services |
280
302
  | `api-telemetry` | OTel catalog: spans, metrics, completion logs, env config, cardinality rules |
281
303
  | `api-testing` | createMockContext, createFetchMock, runToolContract, test patterns |
@@ -294,9 +316,10 @@ Available skills:
294
316
  | `bun run rebuild` | Clean + build |
295
317
  | `bun run clean` | Remove build artifacts |
296
318
  | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
297
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Re-resolves the `^`-ranged framework pin — verify the lock afterwards |
319
+ | `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
320
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
298
321
  | `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
299
- | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity |
322
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, MCPB `user_config` wiring, plugin manifests, README version badge (run by devcheck) |
300
323
  | `bun run list-skills` | Print the skill registry |
301
324
  | `bun run tree` | Generate directory structure doc |
302
325
  | `bun run format` | Auto-fix formatting (safe fixes only) |
@@ -310,6 +333,24 @@ Available skills:
310
333
 
311
334
  ---
312
335
 
336
+ ## Bundling
337
+
338
+ `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies and strips dependency-shipped agent docs and platform-specific native bindings that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP deployments are unaffected.
339
+
340
+ `lint:packaging` verifies that `server.json` and `manifest.json` declare the same env var names, that every `manifest.json` `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.<key>}"` (the host substitutes nothing else), that an optional string option carries `"default": ""`, that no plugin manifest writes an empty `env` value, and that the README `Version-` badge matches `package.json`.
341
+
342
+ ---
343
+
344
+ ## Changelog
345
+
346
+ Directory-based, grouped by minor series via the `.x` semver-wildcard convention. Source of truth: `changelog/<major.minor>.x/<version>.md` — one file per release, shipped in the npm package. At release, author the per-version file with a concrete version and date, then run `bun run changelog:build` to regenerate the rollup. `changelog/template.md` is a **pristine format reference** — never edited or moved. `CHANGELOG.md` is a **navigation index** regenerated by `bun run changelog:build` — devcheck hard-fails on drift; never hand-edit it.
347
+
348
+ Each per-version file opens with YAML frontmatter: `summary` (required, ≤350 chars), optional `breaking: true` for changes consumers must act on, optional `security: true` only for a security fix in this server's own source (never a dependency CVE bump — those go under `## Dependencies`).
349
+
350
+ **Section order:** the Keep a Changelog sequence — Added, Changed, Deprecated, Removed, Fixed, Security — then `Dependencies` last. Include only sections with entries.
351
+
352
+ ---
353
+
313
354
  ## Checklist
314
355
 
315
356
  - [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()`)
@@ -321,4 +362,5 @@ Available skills:
321
362
  - [ ] Every device call goes through `PixooService`; every `PixooResult` checked
322
363
  - [ ] Renderer functions have no device dependency — testable without hardware
323
364
  - [ ] Env var added? Declared in BOTH `server.json` and `manifest.json` (`lint:packaging` enforces parity)
365
+ - [ ] `.codex-plugin/plugin.json` and `.claude-plugin/plugin.json` carry the `package.json` `version`; display fields use the unscoped repo name `pixoo-mcp-server`. A user-supplied variable goes in `env_vars` (`.codex-plugin/mcp.json`) or `userConfig` + `"${user_config.<option>}"` (`.claude-plugin/plugin.json`) — never `"KEY": ""` in `env`
324
366
  - [ ] `bun run devcheck` and `bun run test` pass
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-1.1.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/pixoo-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/pixoo-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pixoo-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-1.1.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/pixoo-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/pixoo-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/pixoo-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -21,9 +21,11 @@
21
21
 
22
22
  ---
23
23
 
24
- ## Tools
24
+ ## Overview
25
25
 
26
- Seven tools covering the full display pipeline — from quick styled text to full layered scene composition, device control, and initial setup:
26
+ Divoom Pixoo LED matrix displays (Pixoo-64 primary; 16 and 32 also supported) on the local network. Render and push styled text, layered scenes, dashboards, and animations, or control device state, from any MCP client. Runs as a stdio process or a local Streamable HTTP server.
27
+
28
+ ### Tools
27
29
 
28
30
  | Tool | Description |
29
31
  |:-----|:------------|
@@ -35,87 +37,118 @@ Seven tools covering the full display pipeline — from quick styled text to ful
35
37
  | `pixoo_discover_devices` | Find Pixoo devices on the local network via Divoom's cloud discovery endpoint. Run once during setup to find device IPs. |
36
38
  | `pixoo_design_brief` | Return craft guidance and live device context for a design topic. Covers legibility rules, palette discipline, layout zones, animation budget, and pre-filled next-tool suggestions. |
37
39
 
38
- ### `pixoo_display_text`
39
-
40
- The primary tool for text-only display. Covers the 80% case — styled text with quality defaults.
40
+ ### Resources
41
41
 
42
- - Named scene themes set background gradient and text palette in one parameter (`midnight`, `ember`, `claude`, `ice`, `neon`, `forest`, `mono`)
43
- - Style block: gradient palette ramps (`ember`, `ice`, `neon`, `fire`, `lavender`, `claude`, `mono`), drop shadow, 1px outline for legibility, integer scale multiplier for block-letter weight
44
- - Semantic positioning: `x: "center"`, `y: "bottom"` — no manual pixel math
45
- - Auto-fit overflow: tries 5×7 → 3×5 → scroll; every fit decision reported in `layout[]`
46
- - Returns the rendered frame as an image content block so you see it immediately
47
- - Optional brightness convenience parameter applied before push
42
+ | Resource | Description |
43
+ |:---|:---|
44
+ | `pixoo://device/status` | Live snapshot of the connected Pixoo display: reachable, channel, brightness, screen state, and display size |
45
+ | `pixoo://reference/themes` | Theme and palette registry with background gradients, default text palettes, accent colors, and swatch values |
46
+ | `pixoo://reference/icons` | Built-in icon names organized by category (weather, arrows, status, media) |
47
+ | `pixoo://reference/design-guide` | Long-form 64px craft guide: legibility floors, palette discipline, layout zones, animation budget, and known device behaviors |
48
48
 
49
- ---
49
+ All resource data is also reachable via tools. `pixoo_design_brief` surfaces the design guide content per topic; `pixoo_control_device` returns live device state equivalent to `pixoo://device/status`.
50
50
 
51
- ### `pixoo_compose_scene`
51
+ ## Capability reference
52
52
 
53
- Full scene composition with the complete element vocabulary.
53
+ ### `pixoo_display_text` <sub>tool</sub>
54
54
 
55
- - Layered elements rendered back-to-front: `text`, `icon`, `rect`, `circle`, `line`, `progress`, `sparkline`, `bitmap`, `pixels`, `image`, `sprite`
56
- - Named icons from the built-in registry (weather, arrows, status, media) or custom SVG path
57
- - Dashboard widgets: `progress` bar with gradient fill and optional label; `sparkline` mini chart (line or bar, auto-scaled)
58
- - Animation: named effect presets (`float`, `scroll-left`, `scroll-right`, `pulse`, `blink`, `twinkle`, `drift`, `fade-in`, `fade-out`) or raw keyframe arrays — 1–40 frames, configurable speed
59
- - Per-element opacity and `visible` flag; images at https URLs fetched server-side to a temp file
60
- - Returns a preview image (static: PNG; animated: labeled contact-sheet PNG + GIF saved to disk)
55
+ - Named scene themes set background gradient and default text palette in one parameter (`midnight`, `ember`, `claude`, `ice`, `neon`, `forest`, `mono`)
56
+ - Style block: palette ramps (`ember`, `ice`, `neon`, `fire`, `lavender`, `claude`, `mono`) or a custom gradient/flat color, optional drop shadow, 1px outline, integer scale 1–8
57
+ - Semantic positioning (`x: "center"`, `y: "bottom"`) or absolute pixel coordinates; multi-line text stacks vertically with configurable alignment
58
+ - Auto-fit overflow tries standard font, then compact, then scroll; every fit decision is reported in `layout[]` with an `action` (`shrunk-to-compact`, `scrolling`, `wrapped`, `truncated`, `clipped`)
59
+ - Optional `brightness` (0–100) applied before push — a failure is a warning via an enrichment notice, not a tool error
60
+ - Returns the rendered frame as an image content block; `outputFiles` is populated only when `PIXOO_OUTPUT_DIR` is configured
61
61
 
62
62
  ---
63
63
 
64
- ### `pixoo_push_image`
64
+ ### `pixoo_compose_scene` <sub>tool</sub>
65
+
66
+ - Up to 50 layered elements rendered back-to-front: `text`, `icon`, `rect`, `circle`, `line`, `progress`, `sparkline`, `bitmap`, `pixels`, `image`, `sprite`
67
+ - Background: solid color, gradient (vertical, horizontal, or radial), or named theme
68
+ - Animation via named effect presets (`float`, `scroll-left`, `scroll-right`, `pulse`, `blink`, `twinkle`, `drift`, `fade-in`, `fade-out`) or raw per-property keyframe arrays — 1–40 frames at 10–2000ms per frame (default 150ms)
69
+ - `image` and `sprite` elements accept an absolute local path or an https URL; a supplied `output` path must be absolute with no traversal segments
70
+ - Static scenes return a PNG preview; animations return a labeled contact-sheet PNG plus a saved GIF (GIF preview is inconsistent across MCP clients)
71
+ - Typed failures for `asset_not_found`, `invalid_color`, and `unknown_icon`, alongside the shared device-error reasons
72
+
73
+ ---
65
74
 
66
- Push any image to the display with control over the downsampling.
75
+ ### `pixoo_push_image` <sub>tool</sub>
67
76
 
68
- - Accepts absolute local paths and https URLs
77
+ - Accepts an absolute local file path or an https (not http) URL
69
78
  - Three fit modes: `contain` (letterbox), `cover` (crop to fill), `fill` (stretch)
70
- - Three resize kernels: `nearest` for pixel art, `lanczos3` for photos, `mitchell` for a balance
71
- - Returns the exact 64×64 result as an image block — you see what the display received
79
+ - Three resize kernels: `nearest` for pixel art (default), `lanczos3` for photos, `mitchell` for a balance
80
+ - Returns the exact resized result as an image content block before it is pushed
72
81
 
73
82
  ---
74
83
 
75
- ### `pixoo_overlay_text`
84
+ ### `pixoo_overlay_text` <sub>tool</sub>
76
85
 
77
- Device-native scrolling text overlay — persists across channel switches.
86
+ - `mode: "set"` adds or updates an overlay on one of 20 independent slots (`id` 0–19); `mode: "clear"` removes it
87
+ - 115 device-rendered font IDs (0–114); overlays persist across channel switches until explicitly cleared
88
+ - Configurable `x`/`y` (0–64), scroll `direction` (`left`/`right`), `speed` (0–100), and `align`; color is `#RRGGBB` hex only — named colors aren't supported here
89
+ - Device-rendered, not previewable — for styled, previewable text use `pixoo_display_text`
78
90
 
79
- - 115 device-rendered font IDs (0–114)
80
- - Up to 20 independent overlay slots (IDs 0–19)
81
- - Configurable scroll direction, speed, and alignment
82
- - Clears with `mode: "clear"` — overlays survive channel changes until explicitly removed
83
- - Not previewable (device-rendered); for styled previewable text use `pixoo_display_text`
91
+ ---
92
+
93
+ ### `pixoo_control_device` <sub>tool</sub>
94
+
95
+ - Call with no params to read state only; supply any of `brightness` (0–100), `screen` (`on`/`off`), `channel` (`faces`/`cloud`/`visualizer`/`custom`), or `clockFaceId` to apply changes before the read-back
96
+ - `applied` lists which requested settings succeeded; a failed setting is omitted from `applied` and reported via an enrichment notice instead of failing the call
97
+ - Always returns current `reachable`, `channel`, `brightness`, `screenOn`, and `clockId` (the latter three absent when the device is unreachable)
84
98
 
85
99
  ---
86
100
 
87
- ### `pixoo_design_brief`
101
+ ### `pixoo_discover_devices` <sub>tool</sub>
88
102
 
89
- The orientation tool. Run before authoring any scene to get grounded in 64px craft constraints.
103
+ - Queries Divoom's cloud discovery endpoint (`app.divoom-gz.com`) — requires internet access even for local device control
104
+ - Returns each device's name, numeric ID, and LAN IP to set as `PIXOO_IP`
105
+ - When `PIXOO_IP` is already configured, flags whether it matches a discovered device (`configuredIpFound`) and notes a mismatch
106
+ - `timeoutMs` configurable 1000–30000ms (default 5000ms)
107
+
108
+ ---
109
+
110
+ ### `pixoo_design_brief` <sub>tool</sub>
90
111
 
91
112
  - Six topics: `text`, `scene`, `dashboard`, `animation`, `pixel-art`, `troubleshooting`
92
- - Returns legibility floors, palette discipline, layout zones, animation budgets, and common pitfalls
93
- - Merges live device state (reachable, channel, brightness, screen) into the response
94
- - Pre-filled `nextToolSuggestions` with ready-to-use arguments based on current device state
113
+ - Returns markdown craft guidance (legibility floors, palette discipline, layout zones, animation budgets) plus a live `deviceContext` snapshot
114
+ - `nextToolSuggestions` are pre-filled with ready-to-use arguments tailored to the topic and current device state (e.g. suggests `pixoo_discover_devices` when the device is unreachable)
115
+ - Also returns `availableThemes` and `iconCategories` for direct use in other tools
95
116
 
96
117
  ---
97
118
 
98
- ## Resources
119
+ ### `pixoo://device/status` <sub>resource</sub>
99
120
 
100
- | Type | Name | Description |
101
- |:-----|:-----|:------------|
102
- | Resource | `pixoo://device/status` | Live snapshot of the connected Pixoo display: reachable, channel, brightness, screen state, and display size |
103
- | Resource | `pixoo://reference/themes` | Theme and palette registry with background gradients, default text palettes, accent colors, and swatch values |
104
- | Resource | `pixoo://reference/icons` | Built-in icon names organized by category (weather, arrows, status, media) |
105
- | Resource | `pixoo://reference/design-guide` | Long-form 64px craft guide: legibility floors, palette discipline, layout zones, animation budget, and known device behaviors |
121
+ - Live snapshot: `reachable`, `channel`, `brightness`, `screenOn`, `clockId`, `displaySize`, `configuredIp`
122
+ - No cache — every read reaches the device; degrades to `reachable: false` instead of erroring when the device is unreachable
123
+ - Equivalent to calling `pixoo_control_device` with no params
106
124
 
107
- All resource data is also reachable via tools. `pixoo_design_brief` surfaces the design guide content per topic; `pixoo_control_device` returns live device state equivalent to `pixoo://device/status`.
125
+ ---
108
126
 
109
- ## Features
127
+ ### `pixoo://reference/themes` <sub>resource</sub>
110
128
 
111
- Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
129
+ - Every registered theme (background gradient or solid, default text palette, accent color, shadow flag) and every named palette (gradient stop pair)
130
+ - `themeNames` / `paletteNames` arrays for direct use in the `theme` / `palette` parameters
131
+ - Compile-time constants — cached for 24h
132
+
133
+ ---
112
134
 
113
- - Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
114
- - Unified error handling — handlers throw, framework catches, classifies, and formats
115
- - Pluggable auth: `none`, `jwt`, `oauth`
116
- - Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
117
- - Structured logging with optional OpenTelemetry tracing
118
- - STDIO and Streamable HTTP transports, serving MCP protocol revision 2026-07-28 alongside the 2025 revisions
135
+ ### `pixoo://reference/icons` <sub>resource</sub>
136
+
137
+ - Every built-in icon name, its category, and its SVG `viewBox`, plus a `byCategory` grouping (weather, arrows, status, media)
138
+ - Use a `name` from this registry in `pixoo_compose_scene` icon elements
139
+ - Compile-time constants — cached for 24h
140
+
141
+ ---
142
+
143
+ ### `pixoo://reference/design-guide` <sub>resource</sub>
144
+
145
+ - Long-form markdown: legibility floors, palette discipline, layout zones (top/middle/bottom strip pixel ranges), animation budget, pixel art rules, and known device behaviors (e.g. channel must be `custom` to show pushed content)
146
+ - `text/markdown` mime type; compile-time constant, cached for 24h
147
+ - Same content `pixoo_design_brief` surfaces per topic — this resource is the complete reference in one document
148
+
149
+ ## Features
150
+
151
+ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): stdio and Streamable HTTP transports, pluggable auth (`none` / `jwt` / `oauth`), swappable storage (`in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`), structured logging with optional OpenTelemetry tracing.
119
152
 
120
153
  Pixoo-specific:
121
154
 
@@ -123,22 +156,18 @@ Pixoo-specific:
123
156
  - All composition happens in an RGBA canvas pipeline on the host (`@cyanheads/pixoo-toolkit`) — the device receives final RGB frames, never raw drawing commands
124
157
  - Styled text engine: gradient palette ramps, drop shadows, outlines, integer scale, semantic alignment — no manual pixel math or bitmap letterforms required
125
158
  - Push pacing: device commands serialized with a configurable minimum inter-push interval (default 1000ms) to prevent device freezes
126
- - Every `PixooResult` checked — `pushed: true` means the device acknowledged with `error_code: 0`, never "I tried"
127
- - Animation capped at 40 frames (device instability beyond this); contact-sheet PNG preview for animations (GIF inconsistent across MCP clients)
128
- - Local transports only — `sharp` image processing doesn't run on Cloudflare Workers
159
+ - Animation capped at 40 frames (device instability beyond this); contact-sheet PNG preview for animations (GIF preview is inconsistent across MCP clients)
129
160
 
130
161
  Agent-friendly output:
131
162
 
132
- - **Preview-as-content**: render tools return the upscaled (8×, 512px) output as an image content block — the calling model sees exactly what was drawn, before and after push
133
- - **Layout transparency**: every silent renderer decision (font fallback, truncation, scroll engaged, element clipped) reported in `layout[]` so agents can inspect and refine
134
- - **Device truth**: `pushed` reflects the device ACK; `deviceState` post-push flags visibility issues (screen off, brightness ≤ 10, wrong channel) as enrichment notices rather than failures
135
- - **Graceful degradation**: render succeeds and returns the preview even when the device is unreachable — the agent keeps its work
163
+ - Preview-as-content — render tools return the upscaled (8×, 512px) output as an image content block, so the calling model sees exactly what was drawn, before and after push
164
+ - Layout transparency — every silent renderer decision (font fallback, truncation, scroll engaged, element clipped) is reported in `layout[]` so agents can inspect and refine
165
+ - Device truth — `pushed` reflects the device ACK; `deviceState` after a push flags visibility issues (screen off, brightness ≤ 10, wrong channel) as enrichment notices rather than failures
166
+ - Graceful degradation — render succeeds and returns the preview even when the device is unreachable, so the agent keeps its work
136
167
 
137
168
  ## Getting started
138
169
 
139
- **Requirements:** A Divoom Pixoo display (Pixoo-64, Pixoo-32, or Pixoo-16) on the same local network as the server. Run `pixoo_discover_devices` to find its IP, then set `PIXOO_IP` in your server configuration.
140
-
141
- Add the following to your MCP client configuration file:
170
+ Add the following to your MCP client configuration file. Run `pixoo_discover_devices` to find your Pixoo's IP, then set `PIXOO_IP` below.
142
171
 
143
172
  ```json
144
173
  {
@@ -204,7 +233,7 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 PIXOO_IP=192.168.1.50 bun run start:h
204
233
 
205
234
  ### Prerequisites
206
235
 
207
- - [Bun v1.3.2](https://bun.sh/) or higher (or Node.js v24+).
236
+ - [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
208
237
  - A Divoom Pixoo LED matrix display on the local network (Pixoo-64, Pixoo-32, or Pixoo-16). Discovery tools and pure-render tools (`push: false`) work without a configured device.
209
238
 
210
239
  ### Installation
@@ -240,13 +269,13 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
240
269
 
241
270
  | Variable | Description | Default |
242
271
  |:---------|:------------|:--------|
243
- | `PIXOO_IP` | Device IP address on the local network. Required for device tools (`pixoo_display_text`, `pixoo_compose_scene`, `pixoo_push_image`, `pixoo_overlay_text`, `pixoo_control_device`). Discovery and pure-render (`push: false`) work without it. | — |
272
+ | `PIXOO_IP` | Device IP address on the local network. **Required for device tools** (`pixoo_display_text`, `pixoo_compose_scene`, `pixoo_push_image`, `pixoo_overlay_text`, `pixoo_control_device`). Discovery and pure-render (`push: false`) work without it. | — |
244
273
  | `PIXOO_SIZE` | Display size in pixels: `16`, `32`, or `64`. | `64` |
245
274
  | `PIXOO_OUTPUT_DIR` | Directory for auto-saving preview PNG and GIF files. When unset, previews are returned in-response only. | — |
246
275
  | `PIXOO_PUSH_MIN_INTERVAL_MS` | Minimum interval between device pushes in milliseconds. Prevents device freeze from rapid-fire commands. | `1000` |
247
276
  | `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
248
277
  | `MCP_HTTP_PORT` | HTTP server port. | `3010` |
249
- | `MCP_SESSION_MODE` | HTTP session handling: `stateful`, `stateless`, or `auto`. Shipped as `stateless` in `.env.example` and the Dockerfile — no tool requests input mid-call. | `auto` (resolves to `stateful`) |
278
+ | `MCP_SESSION_MODE` | HTTP session handling: `stateful`, `stateless`, or `auto`. The server declares `stateless` in source — no tool requests input mid-call — and a value set here overrides it. | `stateless` |
250
279
  | `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |
251
280
  | `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). | `info` |
252
281
  | `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
@@ -290,8 +319,8 @@ The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `
290
319
 
291
320
  ## Project structure
292
321
 
293
- | Path | Purpose |
294
- |:-----|:--------|
322
+ | Directory | Purpose |
323
+ |:----------|:--------|
295
324
  | `src/index.ts` | `createApp()` entry point — registers tools/resources and initializes the Pixoo service. |
296
325
  | `src/config/` | Server-specific environment variable parsing and validation with Zod. |
297
326
  | `src/mcp-server/tools/` | Tool definitions (`*.tool.ts`). |
@@ -307,11 +336,11 @@ See [`CLAUDE.md`/`AGENTS.md`](./CLAUDE.md) for development guidelines and archit
307
336
  - Handlers throw, framework catches — no `try/catch` in tool logic
308
337
  - Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage
309
338
  - The renderer (`src/renderer/`) is pure — no device dependency, testable without hardware
310
- - All device calls go through `PixooService`; every `PixooResult` is checked
339
+ - All device calls go through `PixooService`; every `PixooResult` is checked — never assume a push succeeded
311
340
 
312
341
  ## Contributing
313
342
 
314
- Issues and pull requests are welcome. Run checks and tests before submitting:
343
+ Issues are welcome. Run checks and tests before submitting:
315
344
 
316
345
  ```sh
317
346
  bun run devcheck
@@ -0,0 +1,36 @@
1
+ ---
2
+ summary: "@cyanheads/mcp-ts-core ^0.13.2 adoption: explicit stateless session mode, a structured -32602 argument-rejection envelope, unset-env normalization for PIXOO_* vars, and the framework skill tree moved to framework-skills/. Claude and Codex plugin manifests now forward PIXOO_IP/PIXOO_SIZE."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 1.1.2 — 2026-09-16
8
+
9
+ ## Added
10
+
11
+ - **Plugin device config** — the Claude plugin declares `userConfig` (`pixoo_ip`/`pixoo_size`) wired to `PIXOO_IP`/`PIXOO_SIZE`; the Codex plugin forwards both via `env_vars`. A Codex plugin install previously had no way to set the device IP at all.
12
+ - **Server card publishes the resolved session mode** under `_meta["io.github.cyanheads.mcp-ts-core/sessionMode"]` ([mcp-ts-core#387](https://github.com/cyanheads/mcp-ts-core/issues/387)).
13
+
14
+ ## Changed
15
+
16
+ - **Argument rejections carry `structuredContent.error`** (`code: -32602`, `isError: true`) alongside the existing readable text ([mcp-ts-core#377](https://github.com/cyanheads/mcp-ts-core/issues/377)).
17
+ - **An empty or unsubstituted `${…}` `PIXOO_*` value now reads as unset** rather than as a literal value, through `parseEnvConfig` ([mcp-ts-core#427](https://github.com/cyanheads/mcp-ts-core/issues/427)).
18
+ - **Server identity (name/version) resolves from the served package**, not the working directory ([mcp-ts-core#373](https://github.com/cyanheads/mcp-ts-core/issues/373), [mcp-ts-core#374](https://github.com/cyanheads/mcp-ts-core/issues/374)).
19
+ - Framework skill tree moved `skills/` → `framework-skills/` ([mcp-ts-core#428](https://github.com/cyanheads/mcp-ts-core/issues/428)); scripts and `.github/` templates synced to match.
20
+ - Bun engines floor raised to `>=1.4.0`.
21
+
22
+ ## Fixed
23
+
24
+ - **`sessionMode: 'stateless'` is now declared in `src/index.ts`** — an HTTP run with `MCP_SESSION_MODE` unset resolves `stateless` instead of `stateful`; an explicit value still overrides it ([mcp-ts-core#376](https://github.com/cyanheads/mcp-ts-core/issues/376)).
25
+ - **`SIGTERM`/`SIGINT` now end the process explicitly** once shutdown settles, instead of waiting on the event loop to drain ([mcp-ts-core#435](https://github.com/cyanheads/mcp-ts-core/issues/435)).
26
+
27
+ ## Dependencies
28
+
29
+ - `@cyanheads/mcp-ts-core` ^0.12.3 → ^0.13.2
30
+ - `zod` ^4.4.3 → ^4.6.4
31
+ - `sharp` ^0.35.3 → ^0.35.4
32
+ - `@biomejs/biome` 2.5.9 → 2.5.13
33
+ - `@types/node` 26.2.0 → 26.5.1
34
+ - `ignore` ^7.0.6 → ^7.0.9
35
+ - `tsc-alias` ^1.9.2 → ^1.9.5
36
+ - `vitest` ^4.1.11 → ^5.0.0
@@ -117,30 +117,13 @@ security: false
117
117
  in that unrelated item's metadata.
118
118
 
119
119
  TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
120
- via `gh release create --notes-from-tag`. The tag is a derivative of this
121
- changelog entry — a condensed, scannable version, not a copy. Format:
122
-
123
- <theme — omit version number, GitHub prepends it>
124
- ← blank line
125
- <1-2 sentence context: what this release does>
126
- ← blank line
127
- Dependency bumps: ← section header
128
- ← blank line
129
- - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
130
- ← blank line
131
- Changed: ← only sections with entries
132
- ← blank line
133
- - `format()` output includes `query` in text mode
134
- ← blank line
135
- Added:
136
- ← blank line
137
- - `manifest.json` scaffolded for MCPB bundle support
138
- - Install badges (Claude Desktop, Cursor, VS Code)
139
- ← blank line
140
- <N> tests pass; `bun run devcheck` clean. ← footer
141
-
142
- Never a flat comma-separated string. Always structured markdown with
143
- sections. The tag must scan well as a rendered GitHub Release page.
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): the entry's `summary:` as the
123
+ theme line without the version, flat headline bullets — no Keep-a-Changelog
124
+ section headers, no gates line — at most one deps line, issue backlinks,
125
+ and the changelog link last. In release-PR mode the `git-wrapup` skill
126
+ authors that digest as the PR body's `## Changes` and the tag copies it.
144
127
  -->
145
128
 
146
129
  ## Added
package/dist/index.js CHANGED
@@ -37,6 +37,8 @@ await createApp({
37
37
  pixooDesignGuideResource,
38
38
  ],
39
39
  prompts: [],
40
+ // No handler requests input mid-call, so nothing needs a 2025-era session.
41
+ sessionMode: 'stateless',
40
42
  /**
41
43
  * The tool and resource surface is fixed at build time — nothing registers or
42
44
  * retires a definition at runtime — so the list results are safe for shared
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY;AACZ,OAAO,EAAE,wBAAwB,EAAE,MAAM,mEAAmE,CAAC;AAC7G,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,QAAQ;AACR,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,kBAAkB;IACzB,KAAK,EAAE;QACL,gBAAgB;QAChB,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,oBAAoB;QACpB,gBAAgB;KACjB;IACD,SAAS,EAAE;QACT,yBAAyB;QACzB,mBAAmB;QACnB,kBAAkB;QAClB,wBAAwB;KACzB;IACD,OAAO,EAAE,EAAE;IACX;;;;;OAKG;IACH,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QACxD,gBAAgB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC5D,0BAA0B,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;KACvE;IACD,KAAK,CAAC,IAAI;QACR,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,YAAY,EACV,sGAAsG;QACtG,uHAAuH;QACvH,mGAAmG;CACtG,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY;AACZ,OAAO,EAAE,wBAAwB,EAAE,MAAM,mEAAmE,CAAC;AAC7G,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AAClG,QAAQ;AACR,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,kBAAkB;IACzB,KAAK,EAAE;QACL,gBAAgB;QAChB,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,oBAAoB;QACpB,gBAAgB;KACjB;IACD,SAAS,EAAE;QACT,yBAAyB;QACzB,mBAAmB;QACnB,kBAAkB;QAClB,wBAAwB;KACzB;IACD,OAAO,EAAE,EAAE;IACX,2EAA2E;IAC3E,WAAW,EAAE,WAAW;IACxB;;;;;OAKG;IACH,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QACxD,gBAAgB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC5D,0BAA0B,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;KACvE;IACD,KAAK,CAAC,IAAI;QACR,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,YAAY,EACV,sGAAsG;QACtG,uHAAuH;QACvH,mGAAmG;CACtG,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/pixoo-mcp-server",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "mcpName": "io.github.cyanheads/pixoo-mcp-server",
5
5
  "description": "Render and push styled pixel art, text, dashboards, and animations to Divoom Pixoo LED displays on your local network via MCP. STDIO or Streamable HTTP.",
6
6
  "type": "module",
@@ -24,6 +24,7 @@
24
24
  "rebuild": "bun run scripts/clean.ts && bun run scripts/build.ts",
25
25
  "clean": "bun run scripts/clean.ts",
26
26
  "devcheck": "bun run scripts/devcheck.ts",
27
+ "audit:fix": "bun audit fix",
27
28
  "audit:refresh": "rm -f bun.lock && bun install && bun audit",
28
29
  "tree": "bun run scripts/tree.ts",
29
30
  "list-skills": "bun run scripts/list-skills.ts",
@@ -79,27 +80,27 @@
79
80
  "license": "Apache-2.0",
80
81
  "packageManager": "bun@1.4.0",
81
82
  "engines": {
82
- "bun": ">=1.3.0",
83
+ "bun": ">=1.4.0",
83
84
  "node": ">=24.0.0"
84
85
  },
85
86
  "publishConfig": {
86
87
  "access": "public"
87
88
  },
88
89
  "dependencies": {
89
- "@cyanheads/mcp-ts-core": "^0.12.3",
90
+ "@cyanheads/mcp-ts-core": "^0.13.2",
90
91
  "@cyanheads/pixoo-toolkit": "^0.8.2",
91
92
  "pino-pretty": "^13.1.3",
92
- "sharp": "^0.35.3",
93
- "zod": "^4.4.3"
93
+ "sharp": "^0.35.4",
94
+ "zod": "^4.6.4"
94
95
  },
95
96
  "devDependencies": {
96
- "@biomejs/biome": "2.5.9",
97
+ "@biomejs/biome": "2.5.13",
97
98
  "@socketsecurity/bun-security-scanner": "^1.1.2",
98
- "@types/node": "26.2.0",
99
+ "@types/node": "26.5.1",
99
100
  "depcheck": "^1.4.7",
100
- "ignore": "^7.0.6",
101
- "tsc-alias": "^1.9.2",
101
+ "ignore": "^7.0.9",
102
+ "tsc-alias": "^1.9.5",
102
103
  "typescript": "^7.0.2",
103
- "vitest": "^4.1.11"
104
+ "vitest": "^5.0.0"
104
105
  }
105
106
  }
package/server.json CHANGED
@@ -6,14 +6,14 @@
6
6
  "url": "https://github.com/cyanheads/pixoo-mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.1.1",
9
+ "version": "1.1.2",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "registryBaseUrl": "https://registry.npmjs.org",
14
14
  "identifier": "@cyanheads/pixoo-mcp-server",
15
15
  "runtimeHint": "bun",
16
- "version": "1.1.1",
16
+ "version": "1.1.2",
17
17
  "packageArguments": [
18
18
  {
19
19
  "type": "positional",
@@ -68,7 +68,7 @@
68
68
  "registryBaseUrl": "https://registry.npmjs.org",
69
69
  "identifier": "@cyanheads/pixoo-mcp-server",
70
70
  "runtimeHint": "bun",
71
- "version": "1.1.1",
71
+ "version": "1.1.2",
72
72
  "packageArguments": [
73
73
  {
74
74
  "type": "positional",