@cyanheads/pixoo-mcp-server 1.0.0 → 1.1.1
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 +51 -25
- package/CLAUDE.md +51 -25
- package/Dockerfile +21 -7
- package/LICENSE +1 -1
- package/README.md +3 -2
- package/changelog/1.1.x/1.1.0.md +37 -0
- package/changelog/1.1.x/1.1.1.md +11 -0
- package/changelog/template.md +60 -19
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.js +2 -0
- package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-device-status.resource.d.ts +9 -1
- package/dist/mcp-server/resources/definitions/pixoo-device-status.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-device-status.resource.js +25 -0
- package/dist/mcp-server/resources/definitions/pixoo-device-status.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-icons.resource.d.ts +9 -1
- package/dist/mcp-server/resources/definitions/pixoo-icons.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-icons.resource.js +17 -0
- package/dist/mcp-server/resources/definitions/pixoo-icons.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-themes.resource.d.ts +23 -1
- package/dist/mcp-server/resources/definitions/pixoo-themes.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/pixoo-themes.resource.js +57 -0
- package/dist/mcp-server/resources/definitions/pixoo-themes.resource.js.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.d.ts +77 -76
- package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.js +29 -27
- package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-control-device.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/pixoo-design-brief.tool.d.ts +3 -3
- package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.d.ts +17 -21
- package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.js +5 -14
- package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-overlay-text.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.d.ts +2 -6
- package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.js +13 -42
- package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.js.map +1 -1
- package/dist/renderer/keyframes.js.map +1 -1
- package/dist/renderer/remote-image.d.ts +21 -0
- package/dist/renderer/remote-image.d.ts.map +1 -0
- package/dist/renderer/remote-image.js +64 -0
- package/dist/renderer/remote-image.js.map +1 -0
- package/dist/renderer/scene-renderer.d.ts +9 -3
- package/dist/renderer/scene-renderer.d.ts.map +1 -1
- package/dist/renderer/scene-renderer.js +16 -33
- package/dist/renderer/scene-renderer.js.map +1 -1
- package/dist/renderer/text-engine.js.map +1 -1
- package/dist/services/pixoo/pixoo-service.d.ts.map +1 -1
- package/dist/services/pixoo/pixoo-service.js +2 -2
- package/dist/services/pixoo/pixoo-service.js.map +1 -1
- package/package.json +14 -12
- package/server.json +3 -3
- package/dist/pixoo-mcp-server.mcpb +0 -0
package/AGENTS.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** pixoo-mcp-server
|
|
4
|
-
**Version:** 1.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 1.1.1
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revision 2026-07-28 alongside the 2025 era)
|
|
8
8
|
**Zod:** ^4.4.3
|
|
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.
|
|
@@ -32,8 +32,9 @@ When the user asks what's next or needs direction, suggest options based on the
|
|
|
32
32
|
2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-resource`, `add-prompt` skills
|
|
33
33
|
3. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill
|
|
34
34
|
4. **Run `devcheck`** — lint, format, typecheck, and security audit
|
|
35
|
-
5. **Run the `
|
|
36
|
-
6. **Run the `
|
|
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`
|
|
37
38
|
|
|
38
39
|
Tailor suggestions to what's actually missing or stale — don't recite the full list every time.
|
|
39
40
|
|
|
@@ -44,10 +45,11 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
44
45
|
- **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.
|
|
45
46
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
46
47
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
47
|
-
- **
|
|
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.)
|
|
48
49
|
- **Secrets in env vars only** — never hardcoded.
|
|
49
50
|
- **Every `PixooResult` checked.** No fire-and-forget device calls. `pushed: true` means `error_code: 0` from the device.
|
|
50
|
-
- **
|
|
51
|
+
- **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.
|
|
51
53
|
|
|
52
54
|
---
|
|
53
55
|
|
|
@@ -73,22 +75,25 @@ export const pixooDisplayText = tool('pixoo_display_text', {
|
|
|
73
75
|
push: z.boolean().default(true).describe('Push to device after render.'),
|
|
74
76
|
}),
|
|
75
77
|
output: z.object({
|
|
76
|
-
preview: z.string().describe('Base64-encoded PNG preview of the rendered frame.'),
|
|
77
78
|
pushed: z.boolean().describe('True if the device acknowledged the push.'),
|
|
78
79
|
}),
|
|
79
80
|
async handler(input, ctx) {
|
|
80
81
|
const service = getPixooService();
|
|
81
|
-
const
|
|
82
|
-
ctx.
|
|
83
|
-
|
|
82
|
+
const { preview, pushed } = await renderAndPush(input, service);
|
|
83
|
+
// Rendered bytes go through ctx.content — prepended to content[] and never
|
|
84
|
+
// written to structuredContent, so the base64 is carried once, not twice.
|
|
85
|
+
ctx.content.image(preview, 'image/png');
|
|
86
|
+
ctx.log.info('Text rendered', { pushed });
|
|
87
|
+
return { pushed };
|
|
84
88
|
},
|
|
85
|
-
format: (result) => [
|
|
86
|
-
{ type: 'image', data: result.preview, mimeType: 'image/png' },
|
|
87
|
-
{ type: 'text', text: `Pushed: ${result.pushed}` },
|
|
88
|
-
],
|
|
89
|
+
format: (result) => [{ type: 'text', text: `Pushed: ${result.pushed}` }],
|
|
89
90
|
});
|
|
90
91
|
```
|
|
91
92
|
|
|
93
|
+
**Rendered previews never enter `output`.** Every render tool emits its PNG with
|
|
94
|
+
`ctx.content.image(...)`. Declaring it as an `output` field too would ship the base64
|
|
95
|
+
twice — once in `structuredContent`, once in the `content[]` block.
|
|
96
|
+
|
|
92
97
|
### Resource
|
|
93
98
|
|
|
94
99
|
```ts
|
|
@@ -141,9 +146,14 @@ Handlers receive a unified `ctx` object. Key properties used by this server:
|
|
|
141
146
|
|
|
142
147
|
| Property | Description |
|
|
143
148
|
|:---------|:------------|
|
|
144
|
-
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
145
|
-
| `ctx.
|
|
149
|
+
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
|
|
150
|
+
| `ctx.enrich` | Success-path agent context — `.notice()` / `.total()` / `.echo()` / `.truncated()`. Lands only when the definition declares an `enrichment` block. |
|
|
151
|
+
| `ctx.fail` | Typed throw against the definition's `errors[]` reason union — auto-populates `data.reason`. |
|
|
152
|
+
| `ctx.state` | Tenant-scoped KV — `.get`, `.set(key, value, { ttl? })`, `.delete`, `.getMany`, `.list`. Keys are validated; colons are not legal separators. |
|
|
153
|
+
| `ctx.requestInput` / `ctx.inputs` | Multi-round-trip input. `return ctx.requestInput(...)`; read the answers with `ctx.inputs.accepted(key, schema)` on re-entry. Unused by this server. |
|
|
154
|
+
| `ctx.signal` | `AbortSignal` for cancellation. Pass it to any long-running I/O. |
|
|
146
155
|
| `ctx.requestId` | Unique request ID. |
|
|
156
|
+
| `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
|
|
147
157
|
|
|
148
158
|
---
|
|
149
159
|
|
|
@@ -251,15 +261,26 @@ Available skills:
|
|
|
251
261
|
| `tool-defs-analysis` | Read-only audit of MCP definition language across the surface |
|
|
252
262
|
| `security-pass` | Audit server for MCP-flavored security gaps |
|
|
253
263
|
| `code-simplifier` | Post-session cleanup against `git diff` |
|
|
254
|
-
| `devcheck` | Lint, format, typecheck, audit |
|
|
255
264
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
256
265
|
| `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag |
|
|
257
266
|
| `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker |
|
|
258
267
|
| `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 |
|
|
259
270
|
| `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
271
|
+
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
272
|
+
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
273
|
+
| `api-canvas` | DataCanvas: register tabular data, run SQL, export — Tier 3 opt-in |
|
|
274
|
+
| `api-config` | AppConfig, parseEnvConfig, env vars |
|
|
275
|
+
| `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
|
|
260
276
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
261
|
-
| `api-
|
|
262
|
-
| `api-
|
|
277
|
+
| `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 |
|
|
279
|
+
| `api-services` | LLM, Speech, Graph services |
|
|
280
|
+
| `api-telemetry` | OTel catalog: spans, metrics, completion logs, env config, cardinality rules |
|
|
281
|
+
| `api-testing` | createMockContext, createFetchMock, runToolContract, test patterns |
|
|
282
|
+
| `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
|
|
283
|
+
| `api-workers` | Cloudflare Workers runtime |
|
|
263
284
|
|
|
264
285
|
---
|
|
265
286
|
|
|
@@ -273,11 +294,14 @@ Available skills:
|
|
|
273
294
|
| `bun run rebuild` | Clean + build |
|
|
274
295
|
| `bun run clean` | Remove build artifacts |
|
|
275
296
|
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
276
|
-
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit
|
|
297
|
+
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Re-resolves the `^`-ranged framework pin — verify the lock afterwards |
|
|
298
|
+
| `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 |
|
|
300
|
+
| `bun run list-skills` | Print the skill registry |
|
|
277
301
|
| `bun run tree` | Generate directory structure doc |
|
|
278
302
|
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
279
303
|
| `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff |
|
|
280
|
-
| `
|
|
304
|
+
| `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
|
|
281
305
|
| `bun run start:stdio` | Production mode (stdio) |
|
|
282
306
|
| `bun run start:http` | Production mode (HTTP) |
|
|
283
307
|
| `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
|
|
@@ -288,11 +312,13 @@ Available skills:
|
|
|
288
312
|
|
|
289
313
|
## Checklist
|
|
290
314
|
|
|
291
|
-
- [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types
|
|
315
|
+
- [ ] 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()`)
|
|
316
|
+
- [ ] Tool inputs are strict at the root — an undeclared argument key is rejected by name. Add `.passthrough()` / `.catchall()` only where an open object is genuinely required
|
|
292
317
|
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
293
318
|
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
294
319
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
295
|
-
- [ ] `format()` renders
|
|
320
|
+
- [ ] `format()` renders every `output` field as text — different clients read different surfaces (`structuredContent` vs `content[]`); `lint:mcp` enforces parity. Rendered image bytes go through `ctx.content.image(...)`, never an `output` field
|
|
296
321
|
- [ ] Every device call goes through `PixooService`; every `PixooResult` checked
|
|
297
322
|
- [ ] Renderer functions have no device dependency — testable without hardware
|
|
298
|
-
- [ ] `
|
|
323
|
+
- [ ] Env var added? Declared in BOTH `server.json` and `manifest.json` (`lint:packaging` enforces parity)
|
|
324
|
+
- [ ] `bun run devcheck` and `bun run test` pass
|
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** pixoo-mcp-server
|
|
4
|
-
**Version:** 1.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 1.1.1
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revision 2026-07-28 alongside the 2025 era)
|
|
8
8
|
**Zod:** ^4.4.3
|
|
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.
|
|
@@ -32,8 +32,9 @@ When the user asks what's next or needs direction, suggest options based on the
|
|
|
32
32
|
2. **Add tools/resources/prompts** — scaffold new definitions using the `add-tool`, `add-resource`, `add-prompt` skills
|
|
33
33
|
3. **Field-test definitions** — exercise tools/resources/prompts with real inputs using the `field-test` skill
|
|
34
34
|
4. **Run `devcheck`** — lint, format, typecheck, and security audit
|
|
35
|
-
5. **Run the `
|
|
36
|
-
6. **Run the `
|
|
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`
|
|
37
38
|
|
|
38
39
|
Tailor suggestions to what's actually missing or stale — don't recite the full list every time.
|
|
39
40
|
|
|
@@ -44,10 +45,11 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
44
45
|
- **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.
|
|
45
46
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
46
47
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
47
|
-
- **
|
|
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.)
|
|
48
49
|
- **Secrets in env vars only** — never hardcoded.
|
|
49
50
|
- **Every `PixooResult` checked.** No fire-and-forget device calls. `pushed: true` means `error_code: 0` from the device.
|
|
50
|
-
- **
|
|
51
|
+
- **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.
|
|
51
53
|
|
|
52
54
|
---
|
|
53
55
|
|
|
@@ -73,22 +75,25 @@ export const pixooDisplayText = tool('pixoo_display_text', {
|
|
|
73
75
|
push: z.boolean().default(true).describe('Push to device after render.'),
|
|
74
76
|
}),
|
|
75
77
|
output: z.object({
|
|
76
|
-
preview: z.string().describe('Base64-encoded PNG preview of the rendered frame.'),
|
|
77
78
|
pushed: z.boolean().describe('True if the device acknowledged the push.'),
|
|
78
79
|
}),
|
|
79
80
|
async handler(input, ctx) {
|
|
80
81
|
const service = getPixooService();
|
|
81
|
-
const
|
|
82
|
-
ctx.
|
|
83
|
-
|
|
82
|
+
const { preview, pushed } = await renderAndPush(input, service);
|
|
83
|
+
// Rendered bytes go through ctx.content — prepended to content[] and never
|
|
84
|
+
// written to structuredContent, so the base64 is carried once, not twice.
|
|
85
|
+
ctx.content.image(preview, 'image/png');
|
|
86
|
+
ctx.log.info('Text rendered', { pushed });
|
|
87
|
+
return { pushed };
|
|
84
88
|
},
|
|
85
|
-
format: (result) => [
|
|
86
|
-
{ type: 'image', data: result.preview, mimeType: 'image/png' },
|
|
87
|
-
{ type: 'text', text: `Pushed: ${result.pushed}` },
|
|
88
|
-
],
|
|
89
|
+
format: (result) => [{ type: 'text', text: `Pushed: ${result.pushed}` }],
|
|
89
90
|
});
|
|
90
91
|
```
|
|
91
92
|
|
|
93
|
+
**Rendered previews never enter `output`.** Every render tool emits its PNG with
|
|
94
|
+
`ctx.content.image(...)`. Declaring it as an `output` field too would ship the base64
|
|
95
|
+
twice — once in `structuredContent`, once in the `content[]` block.
|
|
96
|
+
|
|
92
97
|
### Resource
|
|
93
98
|
|
|
94
99
|
```ts
|
|
@@ -141,9 +146,14 @@ Handlers receive a unified `ctx` object. Key properties used by this server:
|
|
|
141
146
|
|
|
142
147
|
| Property | Description |
|
|
143
148
|
|:---------|:------------|
|
|
144
|
-
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
145
|
-
| `ctx.
|
|
149
|
+
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
|
|
150
|
+
| `ctx.enrich` | Success-path agent context — `.notice()` / `.total()` / `.echo()` / `.truncated()`. Lands only when the definition declares an `enrichment` block. |
|
|
151
|
+
| `ctx.fail` | Typed throw against the definition's `errors[]` reason union — auto-populates `data.reason`. |
|
|
152
|
+
| `ctx.state` | Tenant-scoped KV — `.get`, `.set(key, value, { ttl? })`, `.delete`, `.getMany`, `.list`. Keys are validated; colons are not legal separators. |
|
|
153
|
+
| `ctx.requestInput` / `ctx.inputs` | Multi-round-trip input. `return ctx.requestInput(...)`; read the answers with `ctx.inputs.accepted(key, schema)` on re-entry. Unused by this server. |
|
|
154
|
+
| `ctx.signal` | `AbortSignal` for cancellation. Pass it to any long-running I/O. |
|
|
146
155
|
| `ctx.requestId` | Unique request ID. |
|
|
156
|
+
| `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
|
|
147
157
|
|
|
148
158
|
---
|
|
149
159
|
|
|
@@ -251,15 +261,26 @@ Available skills:
|
|
|
251
261
|
| `tool-defs-analysis` | Read-only audit of MCP definition language across the surface |
|
|
252
262
|
| `security-pass` | Audit server for MCP-flavored security gaps |
|
|
253
263
|
| `code-simplifier` | Post-session cleanup against `git diff` |
|
|
254
|
-
| `devcheck` | Lint, format, typecheck, audit |
|
|
255
264
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
256
265
|
| `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag |
|
|
257
266
|
| `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker |
|
|
258
267
|
| `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 |
|
|
259
270
|
| `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
271
|
+
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
272
|
+
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
273
|
+
| `api-canvas` | DataCanvas: register tabular data, run SQL, export — Tier 3 opt-in |
|
|
274
|
+
| `api-config` | AppConfig, parseEnvConfig, env vars |
|
|
275
|
+
| `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
|
|
260
276
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
261
|
-
| `api-
|
|
262
|
-
| `api-
|
|
277
|
+
| `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 |
|
|
279
|
+
| `api-services` | LLM, Speech, Graph services |
|
|
280
|
+
| `api-telemetry` | OTel catalog: spans, metrics, completion logs, env config, cardinality rules |
|
|
281
|
+
| `api-testing` | createMockContext, createFetchMock, runToolContract, test patterns |
|
|
282
|
+
| `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
|
|
283
|
+
| `api-workers` | Cloudflare Workers runtime |
|
|
263
284
|
|
|
264
285
|
---
|
|
265
286
|
|
|
@@ -273,11 +294,14 @@ Available skills:
|
|
|
273
294
|
| `bun run rebuild` | Clean + build |
|
|
274
295
|
| `bun run clean` | Remove build artifacts |
|
|
275
296
|
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
276
|
-
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit
|
|
297
|
+
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Re-resolves the `^`-ranged framework pin — verify the lock afterwards |
|
|
298
|
+
| `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 |
|
|
300
|
+
| `bun run list-skills` | Print the skill registry |
|
|
277
301
|
| `bun run tree` | Generate directory structure doc |
|
|
278
302
|
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
279
303
|
| `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff |
|
|
280
|
-
| `
|
|
304
|
+
| `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
|
|
281
305
|
| `bun run start:stdio` | Production mode (stdio) |
|
|
282
306
|
| `bun run start:http` | Production mode (HTTP) |
|
|
283
307
|
| `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
|
|
@@ -288,11 +312,13 @@ Available skills:
|
|
|
288
312
|
|
|
289
313
|
## Checklist
|
|
290
314
|
|
|
291
|
-
- [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types
|
|
315
|
+
- [ ] 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()`)
|
|
316
|
+
- [ ] Tool inputs are strict at the root — an undeclared argument key is rejected by name. Add `.passthrough()` / `.catchall()` only where an open object is genuinely required
|
|
292
317
|
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
293
318
|
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
294
319
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
295
|
-
- [ ] `format()` renders
|
|
320
|
+
- [ ] `format()` renders every `output` field as text — different clients read different surfaces (`structuredContent` vs `content[]`); `lint:mcp` enforces parity. Rendered image bytes go through `ctx.content.image(...)`, never an `output` field
|
|
296
321
|
- [ ] Every device call goes through `PixooService`; every `PixooResult` checked
|
|
297
322
|
- [ ] Renderer functions have no device dependency — testable without hardware
|
|
298
|
-
- [ ] `
|
|
323
|
+
- [ ] Env var added? Declared in BOTH `server.json` and `manifest.json` (`lint:packaging` enforces parity)
|
|
324
|
+
- [ ] `bun run devcheck` and `bun run test` pass
|
package/Dockerfile
CHANGED
|
@@ -3,16 +3,23 @@
|
|
|
3
3
|
#
|
|
4
4
|
# This stage installs all dependencies (including dev), builds the TypeScript
|
|
5
5
|
# source code into JavaScript, and prepares the production assets.
|
|
6
|
+
#
|
|
7
|
+
# Pinned to $BUILDPLATFORM so a multi-arch build runs `tsc` once, natively. Only
|
|
8
|
+
# `dist/` crosses into the production stage and that output is JavaScript, so it
|
|
9
|
+
# is architecture-independent — emulating this stage buys nothing, and Bun 1.4
|
|
10
|
+
# aborts with MemoryExhaustion under QEMU x86_64 when it is emulated.
|
|
6
11
|
# ==============================================================================
|
|
7
|
-
FROM oven/bun:1.
|
|
12
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build
|
|
8
13
|
|
|
9
14
|
WORKDIR /usr/src/app
|
|
10
15
|
|
|
11
16
|
# Copy dependency manifests for optimized layer caching
|
|
12
17
|
COPY package.json bun.lock ./
|
|
13
18
|
|
|
14
|
-
# Install all dependencies (including dev dependencies for building)
|
|
15
|
-
|
|
19
|
+
# Install all dependencies (including dev dependencies for building).
|
|
20
|
+
# The BuildKit cache mount persists Bun's global package cache across builds.
|
|
21
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
22
|
+
bun install --frozen-lockfile --ignore-scripts
|
|
16
23
|
|
|
17
24
|
# Copy the rest of the source code
|
|
18
25
|
COPY . .
|
|
@@ -28,7 +35,7 @@ RUN bun run build
|
|
|
28
35
|
# application. It uses a slim base image and only includes production
|
|
29
36
|
# dependencies and build artifacts.
|
|
30
37
|
# ==============================================================================
|
|
31
|
-
FROM oven/bun:1.
|
|
38
|
+
FROM oven/bun:1.4.0-slim AS production
|
|
32
39
|
|
|
33
40
|
WORKDIR /usr/src/app
|
|
34
41
|
|
|
@@ -49,14 +56,21 @@ COPY package.json bun.lock ./
|
|
|
49
56
|
|
|
50
57
|
# Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
|
|
51
58
|
# that are not needed in the final production image.
|
|
52
|
-
|
|
59
|
+
# `--omit=peer` drops the framework's optional peer tiers (test runner, service
|
|
60
|
+
# SDKs, parsers) that Bun would otherwise auto-install. Anything this server
|
|
61
|
+
# actually imports belongs in its own `dependencies`, so nothing needed at
|
|
62
|
+
# runtime is lost. The OTEL step below carries the same flag — without it, that
|
|
63
|
+
# install re-resolves the graph and pulls every optional peer back in.
|
|
64
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
65
|
+
bun install --production --omit=peer --frozen-lockfile --ignore-scripts
|
|
53
66
|
|
|
54
67
|
# Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
|
|
55
68
|
# These are not bundled by default to keep the base image lean. Enable at build time
|
|
56
69
|
# with: docker build --build-arg OTEL_ENABLED=true
|
|
57
70
|
ARG OTEL_ENABLED=true
|
|
58
|
-
RUN
|
|
59
|
-
|
|
71
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
72
|
+
if [ "$OTEL_ENABLED" = "true" ]; then \
|
|
73
|
+
bun add --omit=dev --omit=peer --ignore-scripts @hono/otel \
|
|
60
74
|
@opentelemetry/instrumentation-http \
|
|
61
75
|
@opentelemetry/exporter-metrics-otlp-http \
|
|
62
76
|
@opentelemetry/exporter-trace-otlp-http \
|
package/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@ Apache License
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright 2026 Casey Hand @cyanheads
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/pixoo-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/pixoo-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -115,7 +115,7 @@ Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp
|
|
|
115
115
|
- Pluggable auth: `none`, `jwt`, `oauth`
|
|
116
116
|
- Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
|
|
117
117
|
- Structured logging with optional OpenTelemetry tracing
|
|
118
|
-
- STDIO and Streamable HTTP transports
|
|
118
|
+
- STDIO and Streamable HTTP transports, serving MCP protocol revision 2026-07-28 alongside the 2025 revisions
|
|
119
119
|
|
|
120
120
|
Pixoo-specific:
|
|
121
121
|
|
|
@@ -246,6 +246,7 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
|
|
|
246
246
|
| `PIXOO_PUSH_MIN_INTERVAL_MS` | Minimum interval between device pushes in milliseconds. Prevents device freeze from rapid-fire commands. | `1000` |
|
|
247
247
|
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
248
248
|
| `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`) |
|
|
249
250
|
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |
|
|
250
251
|
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). | `info` |
|
|
251
252
|
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "SDK v2 adoption: rendered previews move from `output` to `content[]` (`previewData`/`previewMimeType` removed from 3 tools); fixes a dead path-traversal guard in `pixoo_compose_scene`'s output path (#5)."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 1.1.0 — 2026-08-22
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`cacheHints`** — `src/index.ts` declares 1h `tools/list`/`resources/list`/`resources/templates/list` hints; `pixoo://reference/design-guide`, `pixoo://reference/icons`, and `pixoo://reference/themes` each declare a 24h `cacheHint` (compile-time-constant content). `pixoo://device/status` declares none — live device state.
|
|
12
|
+
- **`output` schemas** on `pixoo://device/status`, `pixoo://reference/icons`, and `pixoo://reference/themes` resources.
|
|
13
|
+
- **`invalid_output_path`** error reason on `pixoo_compose_scene` — thrown when `output` is relative or contains traversal segments.
|
|
14
|
+
- **`MCP_SESSION_MODE`** documented in `.env.example` and the README env table; shipped as `stateless` (matching the Dockerfile) since no tool or resource here requests input mid-call.
|
|
15
|
+
|
|
16
|
+
## Changed
|
|
17
|
+
|
|
18
|
+
- **`pixoo_display_text`, `pixoo_compose_scene`, `pixoo_push_image`** — rendered/pushed images now go through `ctx.content.image(...)` into `content[]` instead of a `previewData`/`previewMimeType` pair on `output`. A client reading `structuredContent.previewData` from these three tools must switch to the image content block; the block was already present, so no client loses the image itself.
|
|
19
|
+
- **Remote image fetch** extracted to `src/renderer/remote-image.ts` (`fetchRemoteImageToTempPng`, `isRemoteSource`), shared by `pixoo_push_image` and the scene renderer's image elements. Uses the framework's `fetchWithTimeout` (15s budget) instead of a bare `fetch`.
|
|
20
|
+
|
|
21
|
+
## Fixed
|
|
22
|
+
|
|
23
|
+
- **`pixoo_compose_scene`'s output-path guard** validated `path.resolve(input.output)` — always absolute and already-normalized, so the guard could never reject anything. A relative path like `../../foo.png` resolved against the process cwd and was written. The raw `input.output` is now checked before resolving (#5).
|
|
24
|
+
|
|
25
|
+
## Dependencies
|
|
26
|
+
|
|
27
|
+
- `@cyanheads/mcp-ts-core` `^0.10.6` → `^0.12.3`
|
|
28
|
+
- `@cyanheads/pixoo-toolkit` `^0.6.1` → `^0.8.2`
|
|
29
|
+
- `sharp` `^0.35.1` → `^0.35.3`
|
|
30
|
+
- `@biomejs/biome` `2.4.16` → `2.5.9` (dev)
|
|
31
|
+
- `@types/node` `25.9.3` → `26.2.0` (dev)
|
|
32
|
+
- `ignore` `^7.0.5` → `^7.0.6` (dev)
|
|
33
|
+
- `tsc-alias` `^1.8.17` → `^1.9.2` (dev)
|
|
34
|
+
- `typescript` `^6.0.3` → `^7.0.2` (dev)
|
|
35
|
+
- `vitest` `^4.1.8` → `^4.1.11` (dev)
|
|
36
|
+
- `@socketsecurity/bun-security-scanner` `^1.1.2` — new (dev), wired as the `bun install` security scanner in `bunfig.toml`
|
|
37
|
+
- Bun `1.3.2` → `1.4.0` (`packageManager`, Dockerfile base images)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Docker build stage pinned to $BUILDPLATFORM — 1.1.0 published no GHCR image; this restores the multi-arch (linux/amd64 + linux/arm64) publish."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 1.1.1 — 2026-08-22
|
|
8
|
+
|
|
9
|
+
## Fixed
|
|
10
|
+
|
|
11
|
+
- **Multi-arch Docker publish** — the build stage now runs `FROM --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build`. Bun 1.4.0 aborts with a JavaScriptCore `MemoryExhaustion` assertion under QEMU x86_64 emulation, so the `linux/amd64` leg of the 1.1.0 `docker buildx` multi-arch build failed and no image published for either architecture — npm, the MCP Registry, and the GitHub Release all shipped fine, only GHCR was missing ([cyanheads/mcp-ts-core#370](https://github.com/cyanheads/mcp-ts-core/issues/370)). Only `dist/` (JavaScript, architecture-independent) crosses into the production stage, so the build stage never needed emulating.
|
package/changelog/template.md
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
# to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
|
|
5
5
|
# with a concrete date.
|
|
6
6
|
|
|
7
|
-
# Required. One-line GitHub Release-style headline. 350 character cap
|
|
8
|
-
# Default short and scannable. Don't pad, don't stitch
|
|
9
|
-
#
|
|
10
|
-
#
|
|
7
|
+
# Required. One-line GitHub Release-style headline. 350 character cap — a
|
|
8
|
+
# ceiling, not a target. Default short and scannable. Don't pad, don't stitch
|
|
9
|
+
# unrelated changes with commas/semicolons into an inventory — pick the
|
|
10
|
+
# headline, like a tag's theme line. Quotes required: unquoted YAML treats
|
|
11
|
+
# `: ` inside the value as a key separator and fails GitHub's strict parser.
|
|
11
12
|
summary: ""
|
|
12
13
|
|
|
13
14
|
# Set `true` when consumers must change code to upgrade: API removals,
|
|
@@ -15,16 +16,19 @@ summary: ""
|
|
|
15
16
|
# usage. Flagged as `Breaking` in the rollup.
|
|
16
17
|
breaking: false
|
|
17
18
|
|
|
18
|
-
# Set `true`
|
|
19
|
-
#
|
|
20
|
-
#
|
|
19
|
+
# Set `true` ONLY for a security fix in THIS project's own source code — a
|
|
20
|
+
# vulnerability or hardening in code you ship. A dependency or transitive CVE
|
|
21
|
+
# bump is routine maintenance, NOT a security release: record it under
|
|
22
|
+
# `## Dependencies` (with the advisory ID) and leave this `false`. When true,
|
|
23
|
+
# pairs with the `## Security` section below and flags `Security` in the rollup.
|
|
21
24
|
security: false
|
|
22
25
|
|
|
23
26
|
# Optional free-form notes for maintenance agents processing this release.
|
|
24
27
|
# Not rendered in CHANGELOG — consumed by agents running `maintenance` on
|
|
25
|
-
# downstream servers.
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
+
# downstream servers. ADOPTION STEPS ONLY — new files to create, fields to
|
|
29
|
+
# populate, one-time migration steps. Never a second rendering of the body:
|
|
30
|
+
# if a body bullet already says it, name the bullet's symbol instead of
|
|
31
|
+
# re-explaining. Omit the field entirely when there's nothing to say.
|
|
28
32
|
# agent-notes: |
|
|
29
33
|
# <instructions for downstream maintenance agents>
|
|
30
34
|
---
|
|
@@ -39,17 +43,54 @@ security: false
|
|
|
39
43
|
each bullet with the symbol or concept name in **bold** so they can skip
|
|
40
44
|
what's irrelevant and zoom in on what's not.
|
|
41
45
|
|
|
42
|
-
Tone: terse, fact-dense, not verbose.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
Tone: terse, fact-dense, not verbose. Bullet shape: **symbol** + what
|
|
47
|
+
changed + at most one consumer-facing caveat. One sentence by default, two
|
|
48
|
+
when the second carries weight — a bullet past ~40 words or three sentences
|
|
49
|
+
is wrong. The depth lives one hop away: the linked issue carries the why,
|
|
50
|
+
the commit diff carries the how. The changelog names what changed and what
|
|
51
|
+
a consumer does about it; a reader who wants mechanism opens the link.
|
|
52
|
+
|
|
53
|
+
Model length on THIS guide, never on the previous entry — entries modeled
|
|
54
|
+
on entries compound.
|
|
55
|
+
|
|
56
|
+
Cut (each has shipped as a wall of text; these are the cruft):
|
|
57
|
+
- History/justification narration — how the bug worked, why the old
|
|
58
|
+
behavior was wrong. One short clause at most; the issue carries the story.
|
|
59
|
+
- Design-rationale defense — "chosen over Y because…", "guarding the
|
|
60
|
+
getter is not enough…". That is the author arguing with a reviewer;
|
|
61
|
+
reviewers read the PR, not the changelog.
|
|
62
|
+
- Defensive unchanged-clauses — "X is unchanged", "byte-identical to
|
|
63
|
+
<prev>". Keep one only where its absence would cause a real misread,
|
|
64
|
+
as a short parenthetical.
|
|
65
|
+
- Edge-case inventories — marker lists, not-flagged lists, escape tables.
|
|
66
|
+
Tests and the issue carry those.
|
|
67
|
+
- Mechanism walkthroughs (JSDoc, CLAUDE.md/AGENTS.md, or the relevant
|
|
68
|
+
skill own those), ceremonial framings ("This release introduces…"),
|
|
69
|
+
backwards-compat paragraphs, file-by-file test enumerations. Prefer
|
|
70
|
+
code/symbol names over English re-explanations.
|
|
71
|
+
|
|
72
|
+
Verified ≠ included: the every-claim-verified-from-the-diff rule bounds
|
|
73
|
+
the TRUTH of what you write, never the AMOUNT.
|
|
74
|
+
|
|
75
|
+
Example — same fact, right size:
|
|
76
|
+
|
|
77
|
+
TOO LONG: **`fetchWithTimeout`'s `timeoutMs` bounds the whole exchange**
|
|
78
|
+
(#341). `fetch` resolves once headers arrive and the deadline was
|
|
79
|
+
cleared as the helper returned, so a peer that answered promptly and
|
|
80
|
+
then stalled the stream held the request open indefinitely. A 2xx
|
|
81
|
+
carrying a body now comes back as a passthrough wrapper that disarms
|
|
82
|
+
the deadline when the body closes, errors, or is cancelled; …
|
|
83
|
+
[+90 more words of mechanism and edge cases]
|
|
84
|
+
|
|
85
|
+
RIGHT: **`fetchWithTimeout`'s `timeoutMs` now bounds the whole
|
|
86
|
+
exchange, not just the headers** (#341). A stalled body aborts with
|
|
87
|
+
the same `Timeout` error; the returned `Response` is a wrapper, so
|
|
88
|
+
identity assertions (`toBe(response)`) no longer hold.
|
|
50
89
|
|
|
51
90
|
Narrative intro: skip by default. Add one short sentence only when the
|
|
52
|
-
release theme genuinely needs framing the bullets can't carry.
|
|
91
|
+
release theme genuinely needs framing the bullets can't carry. When many
|
|
92
|
+
bullets share one upgrade consequence, state it ONCE — intro line or
|
|
93
|
+
agent-notes — never per bullet.
|
|
53
94
|
|
|
54
95
|
Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
|
|
55
96
|
Fixed, Security. Include only sections with entries; delete the rest
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,17 @@ await createApp({
|
|
|
37
37
|
pixooDesignGuideResource,
|
|
38
38
|
],
|
|
39
39
|
prompts: [],
|
|
40
|
+
/**
|
|
41
|
+
* The tool and resource surface is fixed at build time — nothing registers or
|
|
42
|
+
* retires a definition at runtime — so the list results are safe for shared
|
|
43
|
+
* caches to hold. Per-resource `resources/read` lifetimes are declared on the
|
|
44
|
+
* definitions themselves; the live device-status resource declares none.
|
|
45
|
+
*/
|
|
46
|
+
cacheHints: {
|
|
47
|
+
'tools/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
48
|
+
'resources/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
49
|
+
'resources/templates/list': { ttlMs: 3_600_000, cacheScope: 'public' },
|
|
50
|
+
},
|
|
40
51
|
setup(core) {
|
|
41
52
|
initPixooService(core.config, core.storage);
|
|
42
53
|
},
|
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,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;;;;;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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixoo-design-guide.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/pixoo-design-guide.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAuGrD,eAAO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"pixoo-design-guide.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/pixoo-design-guide.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAuGrD,eAAO,MAAM,wBAAwB,2GAyBnC,CAAC"}
|
|
@@ -109,6 +109,8 @@ export const pixooDesignGuideResource = resource('pixoo://reference/design-guide
|
|
|
109
109
|
description: 'Long-form 64px craft guide: legibility floors, palette discipline, layout zones, animation budget, pixel art rules, and known device behaviors. Read this before composing scenes or troubleshooting display quality.',
|
|
110
110
|
mimeType: 'text/markdown',
|
|
111
111
|
params: z.object({}),
|
|
112
|
+
// Compile-time constant — safe for a shared cache to hold for a day.
|
|
113
|
+
cacheHint: { ttlMs: 86_400_000, cacheScope: 'public' },
|
|
112
114
|
handler(_params, _ctx) {
|
|
113
115
|
return DESIGN_GUIDE;
|
|
114
116
|
},
|