@cyanheads/cyanheads-mcp-server 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +30 -26
- package/CLAUDE.md +30 -26
- package/Dockerfile +16 -7
- package/README.md +17 -17
- package/changelog/0.3.x/0.3.3.md +24 -0
- package/changelog/0.3.x/0.3.4.md +33 -0
- package/changelog/0.4.x/0.4.0.md +21 -0
- package/changelog/template.md +5 -3
- package/dist/config/server-config.d.ts +1 -1
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +13 -6
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/{describe.tool.d.ts → describe-entry.tool.d.ts} +9 -9
- package/dist/mcp-server/tools/definitions/describe-entry.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/{describe.tool.js → describe-entry.tool.js} +19 -10
- package/dist/mcp-server/tools/definitions/describe-entry.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/{search.tool.d.ts → search-catalog.tool.d.ts} +9 -9
- package/dist/mcp-server/tools/definitions/search-catalog.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/{search.tool.js → search-catalog.tool.js} +17 -8
- package/dist/mcp-server/tools/definitions/search-catalog.tool.js.map +1 -0
- package/dist/services/catalog/catalog-service.d.ts +14 -3
- package/dist/services/catalog/catalog-service.d.ts.map +1 -1
- package/dist/services/catalog/catalog-service.js +20 -16
- package/dist/services/catalog/catalog-service.js.map +1 -1
- package/dist/services/catalog/embeddings-runtime.d.ts.map +1 -1
- package/dist/services/catalog/embeddings-runtime.js.map +1 -1
- package/dist/services/catalog/remote-catalog-provider.d.ts.map +1 -1
- package/dist/services/catalog/self-record.d.ts +26 -0
- package/dist/services/catalog/self-record.d.ts.map +1 -0
- package/dist/services/catalog/self-record.js +88 -0
- package/dist/services/catalog/self-record.js.map +1 -0
- package/dist/services/catalog/service-instance.d.ts +17 -0
- package/dist/services/catalog/service-instance.d.ts.map +1 -0
- package/dist/services/catalog/service-instance.js +28 -0
- package/dist/services/catalog/service-instance.js.map +1 -0
- package/dist/services/catalog/types.d.ts +2 -0
- package/dist/services/catalog/types.d.ts.map +1 -1
- package/manifest.json +3 -3
- package/package.json +25 -22
- package/server.json +7 -7
- package/dist/mcp-server/tools/definitions/describe.tool.d.ts.map +0 -1
- package/dist/mcp-server/tools/definitions/describe.tool.js.map +0 -1
- package/dist/mcp-server/tools/definitions/search.tool.d.ts.map +0 -1
- package/dist/mcp-server/tools/definitions/search.tool.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** cyanheads-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
|
8
8
|
**Zod:** ^4.4.3
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
A fleet discovery surface for the cyanheads MCP ecosystem. Two tools:
|
|
17
17
|
|
|
18
|
-
- **`
|
|
19
|
-
- **`
|
|
18
|
+
- **`cyanheads_search_catalog`** — semantic search across fleet tools and servers using cosine similarity over Matryoshka-truncated 256-dim embeddings from `Snowflake/snowflake-arctic-embed-m-v1.5`.
|
|
19
|
+
- **`cyanheads_describe_entry`** — returns the description, connection URL, and per-client install snippet for any named tool or server.
|
|
20
20
|
|
|
21
21
|
The catalog (`fleet.json`) is produced by `caseyjhand-portfolio/scripts/build-fleet-json.ts` at portfolio deploy time. Document vectors are baked into the JSON. The server only embeds the user's query at runtime via `@huggingface/transformers`. See `docs/design.md` for the full architecture.
|
|
22
22
|
|
|
23
|
+
The generated catalog does not include this server, so `src/services/catalog/self-record.ts` supplies a static `CatalogRecord` for `cyanheads-mcp-server` that `CatalogService.getServer()` / `getTool()` consult **only after** the remote index misses. A remote entry always wins, so the fallback self-heals to dead code if the generator ever starts emitting one. The record is never part of the vector index, so semantic search does not surface it — only exact-name resolution does.
|
|
24
|
+
|
|
23
25
|
---
|
|
24
26
|
|
|
25
27
|
## What's Next?
|
|
@@ -46,7 +48,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
46
48
|
- **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()`, `validationError()`, etc.) when the error code matters.
|
|
47
49
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
48
50
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
49
|
-
- **Check `ctx.elicit
|
|
51
|
+
- **Check `ctx.elicit`** for presence before calling.
|
|
50
52
|
- **Secrets in env vars only** — never hardcoded.
|
|
51
53
|
- **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.
|
|
52
54
|
|
|
@@ -160,8 +162,7 @@ Handlers receive a unified `ctx` object. Key properties:
|
|
|
160
162
|
|:---------|:------------|
|
|
161
163
|
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
162
164
|
| `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
|
|
163
|
-
| `ctx.elicit` | Ask user for structured input. **Check for presence first:** `if (ctx.elicit) { ... }` |
|
|
164
|
-
| `ctx.sample` | Request LLM completion from the client. **Check for presence first:** `if (ctx.sample) { ... }` |
|
|
165
|
+
| `ctx.elicit` | Ask user for structured input — form call `(message, schema)` or `.url(message, url)` for an external link. **Check for presence first:** `if (ctx.elicit) { ... }` |
|
|
165
166
|
| `ctx.signal` | `AbortSignal` for cancellation. |
|
|
166
167
|
| `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
|
|
167
168
|
| `ctx.requestId` | Unique request ID. |
|
|
@@ -246,7 +247,7 @@ src/
|
|
|
246
247
|
|
|
247
248
|
## Skills
|
|
248
249
|
|
|
249
|
-
Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
|
|
250
|
+
Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry.
|
|
250
251
|
|
|
251
252
|
**Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
252
253
|
|
|
@@ -266,7 +267,6 @@ Available skills:
|
|
|
266
267
|
| `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
|
|
267
268
|
| `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
|
|
268
269
|
| `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
|
|
269
|
-
| `devcheck` | Lint, format, typecheck, audit |
|
|
270
270
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
271
271
|
| `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
|
|
272
272
|
| `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
|
|
@@ -274,13 +274,14 @@ Available skills:
|
|
|
274
274
|
| `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
|
|
275
275
|
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
276
276
|
| `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
277
|
+
| `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
|
|
277
278
|
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
278
279
|
| `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
|
|
279
280
|
| `api-config` | AppConfig, parseConfig, env vars |
|
|
280
281
|
| `api-context` | Context interface, logger, state, progress |
|
|
281
282
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
282
283
|
| `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
|
|
283
|
-
| `api-mirror` | MirrorService: persistent
|
|
284
|
+
| `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
|
|
284
285
|
| `api-services` | LLM, Speech, Graph services |
|
|
285
286
|
| `api-testing` | createMockContext, test patterns |
|
|
286
287
|
| `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
|
|
@@ -295,31 +296,34 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
295
296
|
|
|
296
297
|
## Commands
|
|
297
298
|
|
|
298
|
-
**Runtime:** Scripts use
|
|
299
|
+
**Runtime:** Scripts use Bun's native TypeScript execution — `bun run <cmd>` is the standard invocation. `npm run <cmd>` also works (npm delegates to bun).
|
|
299
300
|
|
|
300
301
|
| Command | Purpose |
|
|
301
302
|
|:--------|:--------|
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
303
|
+
| `bun run build` | Compile TypeScript |
|
|
304
|
+
| `bun run rebuild` | Clean + build |
|
|
305
|
+
| `bun run clean` | Remove build artifacts |
|
|
306
|
+
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
306
307
|
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
308
|
+
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
309
|
+
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity and plugin manifest identity (run by devcheck) |
|
|
310
|
+
| `bun run list-skills` | Print the skill registry |
|
|
311
|
+
| `bun run tree` | Generate directory structure doc |
|
|
312
|
+
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
313
|
+
| `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
|
|
314
|
+
| `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
|
|
315
|
+
| `bun run start:stdio` | Production mode (stdio) |
|
|
316
|
+
| `bun run start:http` | Production mode (HTTP) |
|
|
317
|
+
| `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
|
|
318
|
+
| `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
|
|
319
|
+
| `bun run release:github` | Create GitHub Release from annotated tag (title format: `v<VERSION>: <subject>`) |
|
|
320
|
+
| `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
|
|
317
321
|
|
|
318
322
|
---
|
|
319
323
|
|
|
320
324
|
## Bundling
|
|
321
325
|
|
|
322
|
-
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
326
|
+
`npm 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 (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
323
327
|
|
|
324
328
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
|
|
325
329
|
|
package/CLAUDE.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** cyanheads-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.0`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
|
8
8
|
**Zod:** ^4.4.3
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
A fleet discovery surface for the cyanheads MCP ecosystem. Two tools:
|
|
17
17
|
|
|
18
|
-
- **`
|
|
19
|
-
- **`
|
|
18
|
+
- **`cyanheads_search_catalog`** — semantic search across fleet tools and servers using cosine similarity over Matryoshka-truncated 256-dim embeddings from `Snowflake/snowflake-arctic-embed-m-v1.5`.
|
|
19
|
+
- **`cyanheads_describe_entry`** — returns the description, connection URL, and per-client install snippet for any named tool or server.
|
|
20
20
|
|
|
21
21
|
The catalog (`fleet.json`) is produced by `caseyjhand-portfolio/scripts/build-fleet-json.ts` at portfolio deploy time. Document vectors are baked into the JSON. The server only embeds the user's query at runtime via `@huggingface/transformers`. See `docs/design.md` for the full architecture.
|
|
22
22
|
|
|
23
|
+
The generated catalog does not include this server, so `src/services/catalog/self-record.ts` supplies a static `CatalogRecord` for `cyanheads-mcp-server` that `CatalogService.getServer()` / `getTool()` consult **only after** the remote index misses. A remote entry always wins, so the fallback self-heals to dead code if the generator ever starts emitting one. The record is never part of the vector index, so semantic search does not surface it — only exact-name resolution does.
|
|
24
|
+
|
|
23
25
|
---
|
|
24
26
|
|
|
25
27
|
## What's Next?
|
|
@@ -46,7 +48,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
46
48
|
- **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()`, `validationError()`, etc.) when the error code matters.
|
|
47
49
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
48
50
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
49
|
-
- **Check `ctx.elicit
|
|
51
|
+
- **Check `ctx.elicit`** for presence before calling.
|
|
50
52
|
- **Secrets in env vars only** — never hardcoded.
|
|
51
53
|
- **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.
|
|
52
54
|
|
|
@@ -160,8 +162,7 @@ Handlers receive a unified `ctx` object. Key properties:
|
|
|
160
162
|
|:---------|:------------|
|
|
161
163
|
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
162
164
|
| `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
|
|
163
|
-
| `ctx.elicit` | Ask user for structured input. **Check for presence first:** `if (ctx.elicit) { ... }` |
|
|
164
|
-
| `ctx.sample` | Request LLM completion from the client. **Check for presence first:** `if (ctx.sample) { ... }` |
|
|
165
|
+
| `ctx.elicit` | Ask user for structured input — form call `(message, schema)` or `.url(message, url)` for an external link. **Check for presence first:** `if (ctx.elicit) { ... }` |
|
|
165
166
|
| `ctx.signal` | `AbortSignal` for cancellation. |
|
|
166
167
|
| `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
|
|
167
168
|
| `ctx.requestId` | Unique request ID. |
|
|
@@ -246,7 +247,7 @@ src/
|
|
|
246
247
|
|
|
247
248
|
## Skills
|
|
248
249
|
|
|
249
|
-
Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
|
|
250
|
+
Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry.
|
|
250
251
|
|
|
251
252
|
**Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
252
253
|
|
|
@@ -266,7 +267,6 @@ Available skills:
|
|
|
266
267
|
| `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
|
|
267
268
|
| `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
|
|
268
269
|
| `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
|
|
269
|
-
| `devcheck` | Lint, format, typecheck, audit |
|
|
270
270
|
| `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
271
271
|
| `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
|
|
272
272
|
| `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
|
|
@@ -274,13 +274,14 @@ Available skills:
|
|
|
274
274
|
| `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
|
|
275
275
|
| `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
276
276
|
| `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
277
|
+
| `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
|
|
277
278
|
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
278
279
|
| `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
|
|
279
280
|
| `api-config` | AppConfig, parseConfig, env vars |
|
|
280
281
|
| `api-context` | Context interface, logger, state, progress |
|
|
281
282
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
282
283
|
| `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
|
|
283
|
-
| `api-mirror` | MirrorService: persistent
|
|
284
|
+
| `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
|
|
284
285
|
| `api-services` | LLM, Speech, Graph services |
|
|
285
286
|
| `api-testing` | createMockContext, test patterns |
|
|
286
287
|
| `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
|
|
@@ -295,31 +296,34 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
295
296
|
|
|
296
297
|
## Commands
|
|
297
298
|
|
|
298
|
-
**Runtime:** Scripts use
|
|
299
|
+
**Runtime:** Scripts use Bun's native TypeScript execution — `bun run <cmd>` is the standard invocation. `npm run <cmd>` also works (npm delegates to bun).
|
|
299
300
|
|
|
300
301
|
| Command | Purpose |
|
|
301
302
|
|:--------|:--------|
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
303
|
+
| `bun run build` | Compile TypeScript |
|
|
304
|
+
| `bun run rebuild` | Clean + build |
|
|
305
|
+
| `bun run clean` | Remove build artifacts |
|
|
306
|
+
| `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
306
307
|
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
308
|
+
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
309
|
+
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity and plugin manifest identity (run by devcheck) |
|
|
310
|
+
| `bun run list-skills` | Print the skill registry |
|
|
311
|
+
| `bun run tree` | Generate directory structure doc |
|
|
312
|
+
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
313
|
+
| `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
|
|
314
|
+
| `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
|
|
315
|
+
| `bun run start:stdio` | Production mode (stdio) |
|
|
316
|
+
| `bun run start:http` | Production mode (HTTP) |
|
|
317
|
+
| `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
|
|
318
|
+
| `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
|
|
319
|
+
| `bun run release:github` | Create GitHub Release from annotated tag (title format: `v<VERSION>: <subject>`) |
|
|
320
|
+
| `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
|
|
317
321
|
|
|
318
322
|
---
|
|
319
323
|
|
|
320
324
|
## Bundling
|
|
321
325
|
|
|
322
|
-
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
326
|
+
`npm 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 (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
323
327
|
|
|
324
328
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
|
|
325
329
|
|
package/Dockerfile
CHANGED
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
# This stage installs all dependencies (including dev), builds the TypeScript
|
|
5
5
|
# source code into JavaScript, and prepares the production assets.
|
|
6
6
|
# ==============================================================================
|
|
7
|
-
FROM oven/bun:1.3 AS build
|
|
7
|
+
FROM oven/bun:1.3.14 AS build
|
|
8
8
|
|
|
9
9
|
WORKDIR /usr/src/app
|
|
10
10
|
|
|
11
11
|
# Copy dependency manifests for optimized layer caching
|
|
12
12
|
COPY package.json bun.lock ./
|
|
13
13
|
|
|
14
|
-
# Install all dependencies (including dev dependencies for building)
|
|
15
|
-
|
|
14
|
+
# Install all dependencies (including dev dependencies for building).
|
|
15
|
+
# The BuildKit cache mount persists Bun's global package cache across builds.
|
|
16
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
17
|
+
bun install --frozen-lockfile --ignore-scripts
|
|
16
18
|
|
|
17
19
|
# Copy the rest of the source code
|
|
18
20
|
COPY . .
|
|
@@ -29,7 +31,7 @@ RUN bun scripts/build.ts
|
|
|
29
31
|
# application. It uses a slim base image and only includes production
|
|
30
32
|
# dependencies and build artifacts.
|
|
31
33
|
# ==============================================================================
|
|
32
|
-
FROM oven/bun:1.3-slim AS production
|
|
34
|
+
FROM oven/bun:1.3.14-slim AS production
|
|
33
35
|
|
|
34
36
|
WORKDIR /usr/src/app
|
|
35
37
|
|
|
@@ -38,9 +40,11 @@ WORKDIR /usr/src/app
|
|
|
38
40
|
ENV NODE_ENV=production
|
|
39
41
|
|
|
40
42
|
# OCI image metadata (https://github.com/opencontainers/image-spec/blob/main/annotations.md)
|
|
43
|
+
ARG APP_VERSION
|
|
41
44
|
LABEL org.opencontainers.image.title="cyanheads-mcp-server"
|
|
42
45
|
LABEL org.opencontainers.image.description="Fleet discovery server for the cyanheads MCP ecosystem."
|
|
43
46
|
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
|
47
|
+
LABEL org.opencontainers.image.version="${APP_VERSION}"
|
|
44
48
|
LABEL org.opencontainers.image.source="https://github.com/cyanheads/cyanheads-mcp-server"
|
|
45
49
|
|
|
46
50
|
# Copy dependency manifests
|
|
@@ -48,14 +52,16 @@ COPY package.json bun.lock ./
|
|
|
48
52
|
|
|
49
53
|
# Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
|
|
50
54
|
# that are not needed in the final production image.
|
|
51
|
-
RUN bun
|
|
55
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
56
|
+
bun install --production --frozen-lockfile --ignore-scripts
|
|
52
57
|
|
|
53
58
|
# Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
|
|
54
59
|
# These are not bundled by default to keep the base image lean. Enable at build time
|
|
55
60
|
# with: docker build --build-arg OTEL_ENABLED=true
|
|
56
61
|
ARG OTEL_ENABLED=true
|
|
57
|
-
RUN
|
|
58
|
-
|
|
62
|
+
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
63
|
+
if [ "$OTEL_ENABLED" = "true" ]; then \
|
|
64
|
+
bun add --omit=dev --ignore-scripts @hono/otel \
|
|
59
65
|
@opentelemetry/instrumentation-http \
|
|
60
66
|
@opentelemetry/exporter-metrics-otlp-http \
|
|
61
67
|
@opentelemetry/exporter-trace-otlp-http \
|
|
@@ -96,5 +102,8 @@ ENV MCP_FORCE_CONSOLE_LOGGING="true"
|
|
|
96
102
|
# Expose the port the server listens on
|
|
97
103
|
EXPOSE ${MCP_HTTP_PORT}
|
|
98
104
|
|
|
105
|
+
# Health check using a bun-native fetch (slim image ships no curl/wget)
|
|
106
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD bun -e "fetch('http://localhost:'+(process.env.MCP_HTTP_PORT??'3010')+'/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
107
|
+
|
|
99
108
|
# The command to start the server
|
|
100
109
|
CMD ["bun", "run", "dist/index.js"]
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>@cyanheads/cyanheads-mcp-server</h1>
|
|
3
|
-
<p><b>
|
|
3
|
+
<p><b>Fleet discovery for the cyanheads MCP ecosystem — semantic search + install snippets.</b>
|
|
4
4
|
<div>2 Tools • 0 Resources • 0 Prompts</div>
|
|
5
5
|
</p>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/cyanheads-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/cyanheads-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -33,24 +33,25 @@ Two tools, semantic ranking, hosted catalog. The catalog itself lives at [`casey
|
|
|
33
33
|
|
|
34
34
|
| Tool | Description |
|
|
35
35
|
|:---|:---|
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
36
|
+
| `cyanheads_search_catalog` | Search fleet tools and servers by natural-language query. Returns ranked matches with brief summaries and the owning server. |
|
|
37
|
+
| `cyanheads_describe_entry` | Return the connection URL and per-client install snippets for a named tool or server. |
|
|
38
38
|
|
|
39
|
-
### `
|
|
39
|
+
### `cyanheads_search_catalog`
|
|
40
40
|
|
|
41
41
|
Semantic search across the fleet. Embeds the query with [Snowflake Arctic Embed M v1.5](https://huggingface.co/Snowflake/snowflake-arctic-embed-m-v1.5) (Matryoshka-truncated to 256 dimensions) and computes cosine similarity against the catalog's pre-computed document vectors.
|
|
42
42
|
|
|
43
|
+
- `query` accepts 1-500 characters
|
|
43
44
|
- `scope: "tools"` (default) returns individual tool matches; `scope: "servers"` returns server-level matches
|
|
44
45
|
- `category` filter narrows to one of `research`, `government`, `public-data`, `utility`
|
|
45
46
|
- Configurable `limit` (1-20, default 5) and a server-side `SIMILARITY_FLOOR` threshold drop low-confidence hits
|
|
46
47
|
- Returns `score` (cosine similarity in [0, 1]) on every result for trust calibration
|
|
47
|
-
- `
|
|
48
|
+
- `totalCount` reports the count above the floor before the limit was applied
|
|
48
49
|
|
|
49
50
|
---
|
|
50
51
|
|
|
51
|
-
### `
|
|
52
|
+
### `cyanheads_describe_entry`
|
|
52
53
|
|
|
53
|
-
Resolve a name to its install instructions. Accepts either a tool name (snake_case, e.g. `earthquake_search`) or a server name (kebab-case, e.g. `earthquake-mcp-server`) — auto-detected from the format, or pinned via the `kind` parameter.
|
|
54
|
+
Resolve a name to its install instructions. Accepts either a tool name (snake_case, e.g. `earthquake_search`) or a server name (kebab-case, e.g. `earthquake-mcp-server`), up to 64 characters — auto-detected from the format, or pinned via the `kind` parameter.
|
|
54
55
|
|
|
55
56
|
- For tools: returns the description and the owning server name
|
|
56
57
|
- For servers: returns description, version, npm package, GitHub URL, the full tool list (each tool's name and description), and per-client install snippets — **local (stdio, via `npx`) for every server, plus remote (Streamable HTTP) when a hosted endpoint exists**
|
|
@@ -77,7 +78,7 @@ Fleet-specific:
|
|
|
77
78
|
|
|
78
79
|
## What's in the fleet
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
100+ MCP servers spanning four categories. Each is open source and individually addressable — `cyanheads_describe_entry` returns its direct connection URL alongside the install snippet. It also describes this server: ask for `cyanheads-mcp-server` and you get the front door's own endpoint and install snippets.
|
|
81
82
|
|
|
82
83
|
| Category | Examples |
|
|
83
84
|
|:--|:--|
|
|
@@ -204,11 +205,11 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
|
|
|
204
205
|
| `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path where the MCP server is mounted | `/mcp` |
|
|
205
206
|
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth` | `none` |
|
|
206
207
|
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.) | `info` |
|
|
207
|
-
| `CATALOG_URL` | Remote fleet.json endpoint (schema v2 with baked embeddings). Override to front your own fleet. | `https://caseyjhand.com/fleet.json` |
|
|
208
|
-
| `CATALOG_FETCH_TIMEOUT_MS` | Per-request timeout for fleet.json fetches in ms | `10000` |
|
|
209
|
-
| `CATALOG_REFRESH_SECONDS` | Background poll interval for fleet.json refresh. `0` disables. | `3600` |
|
|
208
|
+
| `CATALOG_URL` | Remote fleet.json endpoint (schema v2 with baked embeddings). Must be an absolute URL. Override to front your own fleet. | `https://caseyjhand.com/fleet.json` |
|
|
209
|
+
| `CATALOG_FETCH_TIMEOUT_MS` | Per-request timeout for fleet.json fetches in ms. Must be > 0. | `10000` |
|
|
210
|
+
| `CATALOG_REFRESH_SECONDS` | Background poll interval for fleet.json refresh. `0` disables; otherwise must be > 0. | `3600` |
|
|
210
211
|
| `EMBEDDING_MODEL_ID` | Hugging Face model id for query embedding. Must match `fleet.json.embeddingModel`. | `Snowflake/snowflake-arctic-embed-m-v1.5` |
|
|
211
|
-
| `SIMILARITY_FLOOR` | Cosine similarity cutoff for `
|
|
212
|
+
| `SIMILARITY_FLOOR` | Cosine similarity cutoff for `cyanheads_search_catalog` results. Must be within `[0, 1]`. | `0.3` |
|
|
212
213
|
| `OTEL_ENABLED` | Enable OpenTelemetry | `false` |
|
|
213
214
|
|
|
214
215
|
To point at a different catalog, change `CATALOG_URL` to your own hosted JSON file. See [`docs/design.md`](./docs/design.md) for the producer-side script and schema.
|
|
@@ -239,9 +240,8 @@ To point at a different catalog, change `CATALOG_URL` to your own hosted JSON fi
|
|
|
239
240
|
|
|
240
241
|
| Directory | Purpose |
|
|
241
242
|
|:---|:---|
|
|
242
|
-
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Two tools — `
|
|
243
|
-
| `src/services/catalog` | Catalog service — remote fleet.json provider with atomic-swap refresh, vector index, snippet builders. |
|
|
244
|
-
| `src/services/embeddings` | Embedding runtime — query-time inference via `@huggingface/transformers`, with an injectable interface for deterministic tests. |
|
|
243
|
+
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Two tools — `cyanheads_search_catalog` and `cyanheads_describe_entry`. |
|
|
244
|
+
| `src/services/catalog` | Catalog service — remote fleet.json provider with atomic-swap refresh, vector index, snippet builders, the self-description fallback record, and the query-time embedding runtime (`@huggingface/transformers`, behind an injectable interface for deterministic tests). |
|
|
245
245
|
| `src/config` | Server-specific environment variable parsing and validation with Zod. |
|
|
246
246
|
| `tests/` | Unit and integration tests, mirroring the `src/` structure. |
|
|
247
247
|
| `docs/` | Design doc and schema reference. |
|
|
@@ -252,7 +252,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
|
|
|
252
252
|
|
|
253
253
|
- Handlers throw, framework catches — no `try/catch` in tool logic
|
|
254
254
|
- Use `ctx.log` for logging, `ctx.state` for storage
|
|
255
|
-
- Register new tools in `src/
|
|
255
|
+
- Register new tools in the `tools` array passed to `createApp()` in `src/index.ts`
|
|
256
256
|
|
|
257
257
|
## Contributing
|
|
258
258
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Adopt @cyanheads/mcp-ts-core ^0.10.6 — server name/title identity, Docker HEALTHCHECK + version label, bundle cleaner, tsx → bun run script migration."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.3.3 — 2026-06-11
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **Server identity pair** — `createApp()` now sets an explicit `name` / `title` of `cyanheads-mcp-server`, so the hyphenated machine name is the display identity on every surface ([#231](https://github.com/cyanheads/mcp-ts-core/issues/231)).
|
|
12
|
+
- **`stdio` / `streamable-http` keywords** added to `package.json` to surface both supported transports in registry search.
|
|
13
|
+
- **`Dockerfile` `HEALTHCHECK`** — bun-native `fetch` against `/healthz` every 30s (slim image ships no `curl`/`wget`), plus an `APP_VERSION` build arg that stamps `org.opencontainers.image.version` ([#217](https://github.com/cyanheads/mcp-ts-core/issues/217)).
|
|
14
|
+
- **`scripts/clean-mcpb.ts`** — post-pack bundle cleaner wired into `bundle`; runs `mcpb clean` then strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach ([#230](https://github.com/cyanheads/mcp-ts-core/issues/230)).
|
|
15
|
+
- **`lint-packaging` checks 8–9** — post-bundle content guard (zero `node_modules/**` agent-doc entries) and entrypoint/manifest identity check (`name`/`title`/`display_name` must equal the unscoped package name) ([#230](https://github.com/cyanheads/mcp-ts-core/issues/230), [#231](https://github.com/cyanheads/mcp-ts-core/issues/231)).
|
|
16
|
+
- **`coerce-boolean-env-flag` antipattern rule** in `check-framework-antipatterns.ts` — flags `z.coerce.boolean()` on env flags (`Boolean("false") === true`), recommending `z.stringbool()`; the scanner now skips comment lines ([#201](https://github.com/cyanheads/mcp-ts-core/issues/201)).
|
|
17
|
+
- **`techniques` skill** — catalog of reusable response/data-shaping patterns; first reference documents outline-on-overflow ([#204](https://github.com/cyanheads/mcp-ts-core/issues/204)).
|
|
18
|
+
|
|
19
|
+
## Changed
|
|
20
|
+
|
|
21
|
+
- **`cyanheads_describe`** — the `ambiguous_kind` error code moved from `InvalidParams` to `ValidationError`; a name colliding across catalog kinds is an application-level validation failure, not a malformed-params protocol error.
|
|
22
|
+
- **Build scripts run under Bun** — every `package.json` script switched from `tsx scripts/*.ts` to `bun run scripts/*.ts`, and `tsx` was dropped from devDependencies ([#205](https://github.com/cyanheads/mcp-ts-core/issues/205)).
|
|
23
|
+
- **`.mcpbignore` dev-dir patterns root-anchored** — leading `/` added to `/.claude/`, `/.agents/`, `/Dockerfile`, etc. so they match only at bundle root and can't strip nested `node_modules` runtime paths ([#207](https://github.com/cyanheads/mcp-ts-core/issues/207)).
|
|
24
|
+
- Dependencies: `@cyanheads/mcp-ts-core` ^0.9.21 → ^0.10.6, `@types/node` ^25.9.1 → ^25.9.3.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Fix unbounded config env vars (#8); adopt @cyanheads/mcp-ts-core ^0.11.0 with a supply-chain install guard, floating-specifier and plugin-manifest lint checks, and native-binding bundle stripping."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.3.4 — 2026-07-26
|
|
8
|
+
|
|
9
|
+
## Fixed
|
|
10
|
+
|
|
11
|
+
- **`server-config.ts` bounds enforcement** — the Zod schema now rejects values outside the bounds it documents: `SIMILARITY_FLOOR` constrained to `[0, 1]`, `CATALOG_FETCH_TIMEOUT_MS` must be positive, `CATALOG_REFRESH_SECONDS` must be `0` or positive, `CATALOG_URL` must be an absolute URL (`z.url()`), and `EMBEDDING_MODEL_ID` must be non-empty. Previously all five accepted any coerced value, including negative timeouts and an out-of-range similarity floor ([#8](https://github.com/cyanheads/cyanheads-mcp-server/issues/8)).
|
|
12
|
+
- New `tests/config/server-config.test.ts` covers the documented defaults and the accept/reject boundary for each of the five env vars.
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
|
|
16
|
+
- **`@cyanheads/mcp-ts-core`** `^0.10.6` → `^0.11.0`; `typescript` `^6.0.3` → `^7.0.2`; `@biomejs/biome` `^2.4.16` → `^2.5.5`; `@types/node` `^25.9.3` → `^26.1.1`; `tsc-alias` `^1.8.17` → `^1.9.1`; `vitest` `^4.1.8` → `^4.1.10`; `ignore` `^7.0.5` → `^7.0.6`.
|
|
17
|
+
- **`package.json` `author`** — canonicalized to `Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)`; `packageManager` field pinned to `bun@1.3.14`.
|
|
18
|
+
- **`bunfig.toml` supply-chain guard** — `[install].minimumReleaseAge` set to 259200s (3 days), blocking newly-published package versions from install; `@cyanheads/mcp-ts-core` is excluded via `minimumReleaseAgeExcludes` so framework releases adopt same-day. `[install.security].scanner` set to `@socketsecurity/bun-security-scanner`.
|
|
19
|
+
- **`Dockerfile`** — base image pinned to `oven/bun:1.3.14` (both stages); `bun install` steps now use a BuildKit cache mount (`--mount=type=cache,target=/root/.bun/install/cache`); the build-stage install adds `--ignore-scripts`; the OTEL peer-dependency install adds `--omit=dev --ignore-scripts`.
|
|
20
|
+
- **`devcheck`'s Outdated check** no longer flags a package as a finding when `Update === Current` — covers versions held back by the new `minimumReleaseAge` guard or a deliberately capped range, and stops flagging `peerDependency` rows (a peer range states a floor, not a version to track).
|
|
21
|
+
- **`devcheck`'s git-dependent checks** (TODOs/FIXMEs, Tracked Secrets, Framework Antipatterns) skip cleanly instead of failing when `.git` is absent (fresh scaffold before `git init`).
|
|
22
|
+
- **`lint-mcp.ts`** passes `packageJson` to the linter only when present, instead of always.
|
|
23
|
+
- **`scripts/clean-mcpb.ts`** / **`lint-packaging.ts` check 8** now also strip and verify zero `node_modules/@duckdb/node-bindings-*/` entries in a built `.mcpb` — a native binding otherwise locks the bundle to the build host's platform and blows past the 25 MB registry cap; `NATIVE_BINDING_ENTRY` is kept identical across both files (unit-tested).
|
|
24
|
+
- **`.gitignore`** — `data/` anchored to `/data/` (was matching `data/` at any depth).
|
|
25
|
+
|
|
26
|
+
## Added
|
|
27
|
+
|
|
28
|
+
- **`scripts/check-dependency-specifiers.ts`** (new `devcheck` step, "Dependency Specifiers") — rejects floating specifiers (`latest`, `*`, `next`/`beta`/`canary`/`rc`) in `package.json`'s dependency sections and `bun.lock`'s `workspaces` maps; `overrides` is held to the strictest rule since a floating override silently re-resolves the vulnerable transitive it was meant to pin. `peerDependencies`/`optionalDependencies` allow `*`/dist-tags but never `latest`.
|
|
29
|
+
- **`lint-packaging.ts` check 10** — validates the new plugin marketplace manifests (`.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, `.codex-plugin/mcp.json`): non-empty descriptions, and that display fields (`name`, server key, `interface.displayName`) carry the unscoped machine name while the `npx -y` install arg carries the full (possibly scoped) `package.json` name. Gated by `devcheck.config.json` `packaging.pluginManifests` (default on).
|
|
30
|
+
- **`.claude-plugin/plugin.json`**, **`.codex-plugin/plugin.json`**, **`.codex-plugin/mcp.json`** — plugin marketplace manifests for Claude Code and Codex install flows.
|
|
31
|
+
- **`.gitattributes`** — normalizes line endings to LF, marks binary asset extensions, and flags `bun.lock`/`CHANGELOG.md`/`docs/tree.md` as `linguist-generated`.
|
|
32
|
+
- **`.github/SECURITY.md`** — vulnerability reporting policy (GitHub Security tab or `casey@caseyjhand.com`).
|
|
33
|
+
- **`.github/FUNDING.yml`** — GitHub Sponsors / Buy Me a Coffee funding links.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Breaking tool rename (cyanheads_search_catalog / cyanheads_describe_entry), input-length bounds, and a self-description fallback for the front door's own server entry"
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.4.0 — 2026-07-26
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **Self-description fallback.** `cyanheads_describe_entry` now resolves `cyanheads-mcp-server` and its own two tools even though the generated fleet catalog excludes the discovery front door. `src/services/catalog/self-record.ts` supplies a static `CatalogRecord` built from this package's own `package.json` (version, description) and its registered tool definitions; `CatalogService.getServer()` / `getTool()` consult it only after a remote-catalog lookup misses, so a future catalog entry for this server takes precedence automatically. The record is excluded from the vector index, so `cyanheads_search_catalog` does not surface it — only exact-name resolution does. ([#7](https://github.com/cyanheads/cyanheads-mcp-server/issues/7))
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **Breaking: both public tools renamed.** `cyanheads_search` → `cyanheads_search_catalog`; `cyanheads_describe` → `cyanheads_describe_entry`. No compatibility aliases — the old names are gone from `tools/list`. Inputs, outputs, errors, and runtime behavior are unchanged. Clients that call either old name directly must switch to the new name; clients that discover tools dynamically pick up the new names automatically on next connect. ([#10](https://github.com/cyanheads/cyanheads-mcp-server/issues/10))
|
|
16
|
+
- **Input length bounds.** `cyanheads_search_catalog.query` is now capped at 500 characters; `cyanheads_describe_entry.name` at 64. Both previously accepted unbounded strings, letting oversized input reach the local embedding model before domain logic could reject it. ([#9](https://github.com/cyanheads/cyanheads-mcp-server/issues/9))
|
|
17
|
+
- **`CatalogService` accessor moved.** `getCatalogService()` now lives in the new leaf module `src/services/catalog/service-instance.ts` instead of `catalog-service.ts`, breaking an import cycle between the tool definitions and the self-record (which derives its tool list from those same definitions). `initCatalogService()` stays in `catalog-service.ts` and installs the instance via the new module's `setCatalogService()`. `shutdown()` is promoted from `CatalogService` onto the `ICatalogService` interface.
|
|
18
|
+
|
|
19
|
+
## Fixed
|
|
20
|
+
|
|
21
|
+
- **`docs/design.md` reconciled against current code.** The search-tool output schema, error contract, and `format()` parity note were stale from before the servers roll-up and enrichment-block rework; the `ICatalogService` sketch was missing `shutdown()`. All brought back in sync with the current definition files. ([#11](https://github.com/cyanheads/cyanheads-mcp-server/issues/11))
|
package/changelog/template.md
CHANGED
|
@@ -15,9 +15,11 @@ summary: ""
|
|
|
15
15
|
# usage. Flagged as `Breaking` in the rollup.
|
|
16
16
|
breaking: false
|
|
17
17
|
|
|
18
|
-
# Set `true`
|
|
19
|
-
#
|
|
20
|
-
#
|
|
18
|
+
# Set `true` ONLY for a security fix in THIS project's own source code — a
|
|
19
|
+
# vulnerability or hardening in code you ship. A dependency or transitive CVE
|
|
20
|
+
# bump is routine maintenance, NOT a security release: record it under
|
|
21
|
+
# `## Dependencies` (with the advisory ID) and leave this `false`. When true,
|
|
22
|
+
# pairs with the `## Security` section below and flags `Security` in the rollup.
|
|
21
23
|
security: false
|
|
22
24
|
|
|
23
25
|
# Optional free-form notes for maintenance agents processing this release.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
7
|
declare const ServerConfigSchema: z.ZodObject<{
|
|
8
|
-
catalogUrl: z.ZodDefault<z.
|
|
8
|
+
catalogUrl: z.ZodDefault<z.ZodURL>;
|
|
9
9
|
catalogFetchTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
10
10
|
catalogRefreshSeconds: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
11
11
|
embeddingModelId: z.ZodDefault<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;;
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;;iBAyDtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAS9C;AAED,uCAAuC;AACvC,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -11,25 +11,29 @@ const ServerConfigSchema = z.object({
|
|
|
11
11
|
* Loaded at server startup via RemoteJsonCatalogProvider.
|
|
12
12
|
*/
|
|
13
13
|
catalogUrl: z
|
|
14
|
-
.
|
|
14
|
+
.url()
|
|
15
15
|
.default('https://caseyjhand.com/fleet.json')
|
|
16
16
|
.describe('URL of the remote fleet.json catalog endpoint.'),
|
|
17
17
|
/**
|
|
18
|
-
* Timeout in milliseconds for the remote catalog fetch.
|
|
18
|
+
* Timeout in milliseconds for the remote catalog fetch. Must be a positive,
|
|
19
|
+
* finite duration — a zero or negative timeout aborts every fetch before it
|
|
20
|
+
* can complete. `z.coerce.number()` already rejects NaN and Infinity.
|
|
19
21
|
*/
|
|
20
22
|
catalogFetchTimeoutMs: z.coerce
|
|
21
23
|
.number()
|
|
24
|
+
.positive()
|
|
22
25
|
.default(10000)
|
|
23
|
-
.describe('HTTP timeout for remote catalog fetch in milliseconds.'),
|
|
26
|
+
.describe('HTTP timeout for remote catalog fetch in milliseconds. Must be > 0.'),
|
|
24
27
|
/**
|
|
25
28
|
* Background poll interval. The service re-fetches fleet.json on this cadence
|
|
26
29
|
* and swaps in the new vector index if `generatedAt` changed.
|
|
27
|
-
* Set to 0 to disable background refresh.
|
|
30
|
+
* Set to 0 to disable background refresh; any other value must be positive.
|
|
28
31
|
*/
|
|
29
32
|
catalogRefreshSeconds: z.coerce
|
|
30
33
|
.number()
|
|
34
|
+
.nonnegative()
|
|
31
35
|
.default(3600)
|
|
32
|
-
.describe('Seconds between background catalog re-fetches. 0 disables background refresh.'),
|
|
36
|
+
.describe('Seconds between background catalog re-fetches. 0 disables background refresh; otherwise must be > 0.'),
|
|
33
37
|
/**
|
|
34
38
|
* Embedding model identifier. Must match `embeddingModel` declared in fleet.json,
|
|
35
39
|
* or the server refuses to load (since vectors live in the same space as the
|
|
@@ -37,14 +41,17 @@ const ServerConfigSchema = z.object({
|
|
|
37
41
|
*/
|
|
38
42
|
embeddingModelId: z
|
|
39
43
|
.string()
|
|
44
|
+
.min(1)
|
|
40
45
|
.default('Snowflake/snowflake-arctic-embed-m-v1.5')
|
|
41
46
|
.describe('Hugging Face model id used for query embedding at search time. Must match fleet.json.embeddingModel.'),
|
|
42
47
|
/**
|
|
43
|
-
* Minimum cosine similarity for a result to surface in
|
|
48
|
+
* Minimum cosine similarity for a result to surface in cyanheads_search_catalog output.
|
|
44
49
|
* Tunable post-launch based on observed query patterns.
|
|
45
50
|
*/
|
|
46
51
|
similarityFloor: z.coerce
|
|
47
52
|
.number()
|
|
53
|
+
.min(0)
|
|
54
|
+
.max(1)
|
|
48
55
|
.default(0.3)
|
|
49
56
|
.describe('Minimum cosine similarity in [0, 1] for a match to appear in search results.'),
|
|
50
57
|
});
|