@cyanheads/cyanheads-mcp-server 0.4.2 → 0.4.3

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.
Files changed (29) hide show
  1. package/AGENTS.md +13 -12
  2. package/CLAUDE.md +13 -12
  3. package/Dockerfile +38 -29
  4. package/README.md +15 -14
  5. package/changelog/0.4.x/0.4.3.md +34 -0
  6. package/dist/index.js +3 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/mcp-server/tools/definitions/describe-entry.tool.d.ts +23 -0
  9. package/dist/mcp-server/tools/definitions/describe-entry.tool.d.ts.map +1 -1
  10. package/dist/mcp-server/tools/definitions/describe-entry.tool.js +116 -95
  11. package/dist/mcp-server/tools/definitions/describe-entry.tool.js.map +1 -1
  12. package/dist/mcp-server/tools/definitions/search-catalog.tool.d.ts +11 -0
  13. package/dist/mcp-server/tools/definitions/search-catalog.tool.d.ts.map +1 -1
  14. package/dist/mcp-server/tools/definitions/search-catalog.tool.js +82 -20
  15. package/dist/mcp-server/tools/definitions/search-catalog.tool.js.map +1 -1
  16. package/dist/services/catalog/catalog-service.d.ts +2 -2
  17. package/dist/services/catalog/catalog-service.d.ts.map +1 -1
  18. package/dist/services/catalog/catalog-service.js +29 -11
  19. package/dist/services/catalog/catalog-service.js.map +1 -1
  20. package/dist/services/catalog/remote-catalog-provider.d.ts +2 -2
  21. package/dist/services/catalog/remote-catalog-provider.d.ts.map +1 -1
  22. package/dist/services/catalog/remote-catalog-provider.js +34 -5
  23. package/dist/services/catalog/remote-catalog-provider.js.map +1 -1
  24. package/dist/services/catalog/self-record.js +3 -3
  25. package/dist/services/catalog/types.d.ts +2 -2
  26. package/dist/services/catalog/types.d.ts.map +1 -1
  27. package/manifest.json +1 -1
  28. package/package.json +10 -9
  29. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** cyanheads-mcp-server
4
- **Version:** 0.4.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
4
+ **Version:** 0.4.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.10`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/server` 2.0.0
7
+ **MCP SDK:** `@modelcontextprotocol/server` 2.1.0
8
8
  **Zod:** ^4.6.5
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.
@@ -20,7 +20,7 @@ A fleet discovery surface for the cyanheads MCP ecosystem. Two tools:
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.
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 namespace has no candidate. Exact remote names win, then unique case-insensitive remote names; ambiguous folds never fall through to self. Output names are canonical. The self record is never part of the vector index, so semantic search does not surface it — only name resolution does.
24
24
 
25
25
  ---
26
26
 
@@ -67,7 +67,7 @@ export const searchItems = tool('search_items', {
67
67
  annotations: { readOnlyHint: true },
68
68
  input: z.object({
69
69
  query: z.string().describe('Search terms'),
70
- limit: z.number().default(10).describe('Max results'),
70
+ limit: z.number().int().min(1).max(100).default(10).describe('Max results (1–100)'),
71
71
  }),
72
72
  output: z.object({
73
73
  items: z.array(z.object({
@@ -188,13 +188,14 @@ Handlers receive a unified `ctx` object. Key properties:
188
188
  | Property | Description |
189
189
  |:---------|:------------|
190
190
  | `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. |
191
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
191
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any JSON-serializable value; reads return its JSON form (a `Date` comes back as an ISO string). |
192
192
  | `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
193
- | `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
193
+ | `ctx.inputs` | The request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped` — limited to what the client declared (`elicitation` and its form/url modes, `sampling`, `roots`). Client-supplied: a consent gate trusts only a `ctx.state` record it stored when it asked, bound to the operation, caller, and target (see the `api-context` skill). |
194
+ | `ctx.clientCapabilities` | What the client declared for this request, `undefined` when no view exists. Decides whether to ask for optional context (e.g. roots); never a reason to skip a consent prompt. |
194
195
  | `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
195
196
  | `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
196
197
  | `ctx.signal` | `AbortSignal` for cancellation. |
197
- | `ctx.requestId` | Unique request ID. |
198
+ | `ctx.requestId` | Request ID — the one every log record of the call carries and its error envelope returns as `data.requestId`. |
198
199
  | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
199
200
 
200
201
  ---
@@ -203,7 +204,7 @@ Handlers receive a unified `ctx` object. Key properties:
203
204
 
204
205
  Handlers throw — the framework catches, classifies, and formats.
205
206
 
206
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Forwarding it is lint-enforced per throw site (`error-contract-recovery-unforwarded`). Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
207
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. The framework puts it on the wire whenever a failure carrying that `reason` arrives without a hint — a bare `ctx.fail('reason')` or a service throw with `data: { reason }` — as `data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim; override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Every error envelope also carries `data.requestId`, the id the server's log records for that call carry, and `content[]` closes with `(reason … · request <id>)`. Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
207
208
 
208
209
  ```ts
209
210
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -215,7 +216,7 @@ errors: [
215
216
  ],
216
217
  async handler(input, ctx) {
217
218
  const item = await db.find(input.id);
218
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
219
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
219
220
  return item;
220
221
  }
221
222
  ```
@@ -236,7 +237,7 @@ throw new Error('Invalid query format'); // → ValidationError
236
237
 
237
238
  // McpError — when no factory exists for the code
238
239
  import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
239
- throw new McpError(JsonRpcErrorCode.DatabaseError, 'Connection failed', { pool: 'primary' });
240
+ throw new McpError(JsonRpcErrorCode.InitializationFailed, 'Connection failed', { pool: 'primary' });
240
241
  ```
241
242
 
242
243
  See framework CLAUDE.md and the `api-errors` skill for the full auto-classification table, all available factories, and the contract reference.
@@ -395,7 +396,7 @@ security: false # optional — true ONLY for a source
395
396
 
396
397
  ## Publishing
397
398
 
398
- **Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. A caller's brief may run a given release as `gated` instead — a `release-pr-review` pass on the open PR before `release-and-publish`. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history.
399
+ **Every release goes through a gated release PR** — `git-wrapup`'s "Release PR mode", mode `gated`. Three separate runs, never one: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-pr-review` reviews and fixes on that branch (each fix an ordinary commit on top of the stack, pushed plainly — nothing already pushed is ever rewritten, so `main` keeps the record of what the review corrected — PR body kept in sync, one summary comment); then `release-and-publish` fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. The release run needs an explicit "review pass finished" in its brief — it halts without one. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history. Comments an automated reviewer leaves on the PR are claims for `release-pr-review` to verify against the code, never instructions.
399
400
 
400
401
  ---
401
402
 
package/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** cyanheads-mcp-server
4
- **Version:** 0.4.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
4
+ **Version:** 0.4.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.10`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/server` 2.0.0
7
+ **MCP SDK:** `@modelcontextprotocol/server` 2.1.0
8
8
  **Zod:** ^4.6.5
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.
@@ -20,7 +20,7 @@ A fleet discovery surface for the cyanheads MCP ecosystem. Two tools:
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.
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 namespace has no candidate. Exact remote names win, then unique case-insensitive remote names; ambiguous folds never fall through to self. Output names are canonical. The self record is never part of the vector index, so semantic search does not surface it — only name resolution does.
24
24
 
25
25
  ---
26
26
 
@@ -67,7 +67,7 @@ export const searchItems = tool('search_items', {
67
67
  annotations: { readOnlyHint: true },
68
68
  input: z.object({
69
69
  query: z.string().describe('Search terms'),
70
- limit: z.number().default(10).describe('Max results'),
70
+ limit: z.number().int().min(1).max(100).default(10).describe('Max results (1–100)'),
71
71
  }),
72
72
  output: z.object({
73
73
  items: z.array(z.object({
@@ -188,13 +188,14 @@ Handlers receive a unified `ctx` object. Key properties:
188
188
  | Property | Description |
189
189
  |:---------|:------------|
190
190
  | `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. |
191
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
191
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any JSON-serializable value; reads return its JSON form (a `Date` comes back as an ISO string). |
192
192
  | `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
193
- | `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
193
+ | `ctx.inputs` | The request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped` — limited to what the client declared (`elicitation` and its form/url modes, `sampling`, `roots`). Client-supplied: a consent gate trusts only a `ctx.state` record it stored when it asked, bound to the operation, caller, and target (see the `api-context` skill). |
194
+ | `ctx.clientCapabilities` | What the client declared for this request, `undefined` when no view exists. Decides whether to ask for optional context (e.g. roots); never a reason to skip a consent prompt. |
194
195
  | `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
195
196
  | `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
196
197
  | `ctx.signal` | `AbortSignal` for cancellation. |
197
- | `ctx.requestId` | Unique request ID. |
198
+ | `ctx.requestId` | Request ID — the one every log record of the call carries and its error envelope returns as `data.requestId`. |
198
199
  | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
199
200
 
200
201
  ---
@@ -203,7 +204,7 @@ Handlers receive a unified `ctx` object. Key properties:
203
204
 
204
205
  Handlers throw — the framework catches, classifies, and formats.
205
206
 
206
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Forwarding it is lint-enforced per throw site (`error-contract-recovery-unforwarded`). Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
207
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. The framework puts it on the wire whenever a failure carrying that `reason` arrives without a hint — a bare `ctx.fail('reason')` or a service throw with `data: { reason }` — as `data.recovery.hint`, mirrored into `content[]` text unless the message already contains it verbatim; override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Every error envelope also carries `data.requestId`, the id the server's log records for that call carry, and `content[]` closes with `(reason … · request <id>)`. Mark an entry the service layer throws with `thrownBy: 'service'` so `error-contract-unthrown` skips it — lint-only metadata, nothing at runtime reads it. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`, `RequestCancelled`) bubble freely and don't need declaring.
207
208
 
208
209
  ```ts
209
210
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -215,7 +216,7 @@ errors: [
215
216
  ],
216
217
  async handler(input, ctx) {
217
218
  const item = await db.find(input.id);
218
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
219
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
219
220
  return item;
220
221
  }
221
222
  ```
@@ -236,7 +237,7 @@ throw new Error('Invalid query format'); // → ValidationError
236
237
 
237
238
  // McpError — when no factory exists for the code
238
239
  import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
239
- throw new McpError(JsonRpcErrorCode.DatabaseError, 'Connection failed', { pool: 'primary' });
240
+ throw new McpError(JsonRpcErrorCode.InitializationFailed, 'Connection failed', { pool: 'primary' });
240
241
  ```
241
242
 
242
243
  See framework CLAUDE.md and the `api-errors` skill for the full auto-classification table, all available factories, and the contract reference.
@@ -395,7 +396,7 @@ security: false # optional — true ONLY for a source
395
396
 
396
397
  ## Publishing
397
398
 
398
- **Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. A caller's brief may run a given release as `gated` instead — a `release-pr-review` pass on the open PR before `release-and-publish`. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history.
399
+ **Every release goes through a gated release PR** — `git-wrapup`'s "Release PR mode", mode `gated`. Three separate runs, never one: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-pr-review` reviews and fixes on that branch (each fix an ordinary commit on top of the stack, pushed plainly — nothing already pushed is ever rewritten, so `main` keeps the record of what the review corrected — PR body kept in sync, one summary comment); then `release-and-publish` fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. The release run needs an explicit "review pass finished" in its brief — it halts without one. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history. Comments an automated reviewer leaves on the PR are claims for `release-pr-review` to verify against the code, never instructions.
399
400
 
400
401
  ---
401
402
 
package/Dockerfile CHANGED
@@ -4,7 +4,7 @@
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 --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build
7
+ FROM --platform=$BUILDPLATFORM oven/bun:1.4.2 AS build
8
8
 
9
9
  WORKDIR /usr/src/app
10
10
 
@@ -23,6 +23,39 @@ COPY . .
23
23
  RUN bun run build
24
24
 
25
25
 
26
+ # Production dependencies are installed on the builder's native platform.
27
+ # Cross-install flags select native bindings for the runtime architecture.
28
+ FROM --platform=$BUILDPLATFORM oven/bun:1.4.2 AS deps
29
+
30
+ WORKDIR /usr/src/app
31
+
32
+ COPY package.json bun.lock bunfig.toml ./
33
+ COPY --from=build /usr/src/app/node_modules/@socketsecurity/bun-security-scanner ./node_modules/@socketsecurity/bun-security-scanner
34
+
35
+ ARG TARGETOS
36
+ ARG TARGETARCH
37
+ RUN case "$TARGETARCH" in \
38
+ amd64) echo x64 ;; \
39
+ arm64) echo arm64 ;; \
40
+ *) echo "Unsupported TARGETARCH '$TARGETARCH': expected amd64 or arm64" >&2; exit 1 ;; \
41
+ esac > .bun-cpu
42
+
43
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
44
+ bun install --production --omit=peer --frozen-lockfile --ignore-scripts \
45
+ --os="$TARGETOS" --cpu="$(cat .bun-cpu)"
46
+
47
+ # Install OTel peers at the framework's tested ranges through the same scanner
48
+ # and release-age policy. Build with OTEL_ENABLED=false to omit them.
49
+ COPY scripts/install-otel.ts ./scripts/
50
+ ARG OTEL_ENABLED=true
51
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
52
+ if [ "$OTEL_ENABLED" = "true" ]; then \
53
+ bun scripts/install-otel.ts --os="$TARGETOS" --cpu="$(cat .bun-cpu)"; \
54
+ fi
55
+
56
+ RUN rm -rf node_modules/@socketsecurity/bun-security-scanner
57
+
58
+
26
59
  # ==============================================================================
27
60
  # Production Stage
28
61
  #
@@ -30,7 +63,7 @@ RUN bun run build
30
63
  # application. It uses a slim base image and only includes production
31
64
  # dependencies and build artifacts.
32
65
  # ==============================================================================
33
- FROM oven/bun:1.4.0-slim AS production
66
+ FROM oven/bun:1.4.2-slim AS production
34
67
 
35
68
  WORKDIR /usr/src/app
36
69
 
@@ -46,32 +79,9 @@ LABEL org.opencontainers.image.licenses="Apache-2.0"
46
79
  LABEL org.opencontainers.image.version="${APP_VERSION}"
47
80
  LABEL org.opencontainers.image.source="https://github.com/cyanheads/cyanheads-mcp-server"
48
81
 
49
- # Copy dependency manifests
50
- COPY package.json bun.lock ./
51
-
52
- # Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
53
- # that are not needed in the final production image. `--omit=peer` excludes the
54
- # framework's optional peer tiers; direct runtime imports remain in dependencies.
55
- RUN --mount=type=cache,target=/root/.bun/install/cache \
56
- bun install --production --omit=peer --frozen-lockfile --ignore-scripts
57
-
58
- # Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
59
- # These are not bundled by default to keep the base image lean. Enable at build time
60
- # with: docker build --build-arg OTEL_ENABLED=true
61
- ARG OTEL_ENABLED=true
62
- RUN --mount=type=cache,target=/root/.bun/install/cache \
63
- if [ "$OTEL_ENABLED" = "true" ]; then \
64
- bun add --omit=dev --omit=peer --ignore-scripts @hono/otel \
65
- @opentelemetry/instrumentation-http \
66
- @opentelemetry/exporter-metrics-otlp-http \
67
- @opentelemetry/exporter-trace-otlp-http \
68
- @opentelemetry/instrumentation-pino \
69
- @opentelemetry/resources \
70
- @opentelemetry/sdk-metrics \
71
- @opentelemetry/sdk-node \
72
- @opentelemetry/sdk-trace-node \
73
- @opentelemetry/semantic-conventions; \
74
- fi
82
+ # Keep the original manifest: the OTel install changes the deps-stage copy.
83
+ COPY package.json ./
84
+ COPY --from=deps /usr/src/app/node_modules ./node_modules
75
85
 
76
86
  # Copy the compiled application code from the build stage
77
87
  COPY --from=build /usr/src/app/dist ./dist
@@ -97,7 +107,6 @@ ENV MCP_TRANSPORT_TYPE="http"
97
107
  ENV MCP_SESSION_MODE="stateless"
98
108
  ENV MCP_LOG_LEVEL="info"
99
109
  ENV LOGS_DIR="/var/log/cyanheads-mcp-server"
100
- ENV MCP_FORCE_CONSOLE_LOGGING="true"
101
110
 
102
111
  # Expose the port the server listens on
103
112
  EXPOSE ${MCP_HTTP_PORT}
package/README.md CHANGED
@@ -7,13 +7,13 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.4.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/cyanheads-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/cyanheads-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/cyanheads-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-%3E=1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.4.3-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/cyanheads-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-2.1.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/cyanheads-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/cyanheads-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-1.4.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
14
14
  <div align="center">
15
15
 
16
- [![Install in Claude Desktop](https://img.shields.io/badge/Install_in-Claude_Desktop-D97757?style=for-the-badge&logo=anthropic&logoColor=white)](https://github.com/cyanheads/cyanheads-mcp-server/releases/latest/download/cyanheads-mcp-server.mcpb) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=cyanheads-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvY3lhbmhlYWRzLW1jcC1zZXJ2ZXIiXX0=) [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22cyanheads-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads/cyanheads-mcp-server%22%5D%7D)
16
+ [![Install in Claude Desktop](https://img.shields.io/badge/Install_in-Claude_Desktop-D97757?style=for-the-badge&logo=anthropic&logoColor=white)](https://github.com/cyanheads/cyanheads-mcp-server/releases/latest/download/cyanheads-mcp-server.mcpb) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=cyanheads-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvY3lhbmhlYWRzLW1jcC1zZXJ2ZXIiXX0=) [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22cyanheads-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads%2Fcyanheads-mcp-server%22%5D%7D)
17
17
 
18
18
  [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-67E8F9?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
19
19
 
@@ -42,23 +42,19 @@ Fleet discovery for the cyanheads MCP ecosystem, built on a hosted `fleet.json`
42
42
 
43
43
  ### `cyanheads_search_catalog` <sub>tool</sub>
44
44
 
45
- - `query` 1–500 characters; `scope` selects `tools` (default) or `servers` result granularity
46
- - Optional `category` filter: `research`, `government`, `public-data`, `utility`
47
- - `limit` 1–20 (default 5); results below the `SIMILARITY_FLOOR` (default `0.3`) are dropped before the limit applies
48
- - Every result carries `score` (cosine similarity, `[0, 1]`), comparable only within one response
49
- - For scope `tools`, a `servers` roll-up (top 10 by best-matching tool, `serversTotal` for the full count) summarizes which servers matched
50
- - Throws retryable `catalog_empty` while the catalog is still loading
45
+ - `query` 1–500 raw characters, with non-whitespace text required; surrounding whitespace is trimmed before embedding and echo. `scope` selects `tools` (default) or `servers`; optional `category`: `research`, `government`, `public-data`, `utility`; `limit` 1–20 (default 5).
46
+ - Results carry cosine-similarity `score` (`[0, 1]`, comparable within one response). Tool searches include a `servers` roll-up with ten entries per page and `serversTotal`; an unloaded catalog returns retryable `catalog_empty`.
47
+ - Page results with `offset` and the tools-scope roll-up independently with `serversOffset` (both default to 0). Reuse the same query, scope, category, and limit with `nextOffset` / `nextServersOffset`; null means exhausted. Each call uses the current catalog, so a refresh between pages can change ordering. Servers scope requires `serversOffset: 0` and omits roll-up fields.
48
+ - `SIMILARITY_FLOOR` (default `0.3`) filters matches before the limit applies.
51
49
 
52
50
  ---
53
51
 
54
52
  ### `cyanheads_describe_entry` <sub>tool</sub>
55
53
 
56
- - `name` 1–64 characters; accepts a snake_case tool name or kebab-case server name, auto-detected or pinned via `kind`
57
- - Tool lookups return the description and owning server; server lookups return version, npm package, GitHub URL, the full tool list, and per-client install snippets
58
- - `client` filters snippets to one of `claude-code`, `codex`, `cursor`, `gemini`, `streamable-http`, `curl`; omit for every client
59
- - Local (stdio, via `npx`) snippets are returned for every published server; remote (Streamable HTTP) snippets are added only when a hosted endpoint exists
60
- - Discriminated on `kind` (`tool` | `server`) so callers branch on data, not string parsing
61
- - Throws `not_found` (unknown name), `ambiguous_kind` (name matches both a tool and a server — pass `kind` to disambiguate), or retryable `catalog_empty`
54
+ - `name` 1–64 characters accepts a tool or server name, auto-detected or pinned via `kind`. Exact names win, then unique case-insensitive names; output uses canonical names. `client` optionally selects `claude-code`, `codex`, `cursor`, `gemini`, `streamable-http`, or `curl`.
55
+ - Both kinds return connection metadata and install snippets; server results also include the full tool inventory. Published servers get local snippets; hosted servers also get HTTP snippets. For local-only entries, `client: "curl"` returns successful metadata with an `installNotice` naming a stdio client to try. Required environment variables remain visible even without snippets.
56
+ - Descriptions are catalog text; obtain tool schemas from the connected server's `tools/list`.
57
+ - Failures return `not_found`, `ambiguous_kind` (set `kind`), or retryable `catalog_empty`.
62
58
 
63
59
  ## Features
64
60
 
@@ -67,6 +63,7 @@ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): s
67
63
  Catalog-specific:
68
64
 
69
65
  - Hourly background catalog refresh (`CATALOG_REFRESH_SECONDS`, default `3600`) with an atomic index swap when `generatedAt` changes — no restart needed
66
+ - Empty catalogs and conflicting duplicate identities fail before index replacement; refresh retains the last valid catalog. Identical duplicates collapse before indexing, with a bounded load-time warning; servers with no tools remain valid.
70
67
  - Query embeddings are computed at request time via `@huggingface/transformers`; document embeddings are pre-computed, L2-normalized, and Matryoshka-truncated, shipped inside `fleet.json`
71
68
  - The embedding model is warmed up during startup, before OpenTelemetry's HTTP instrumentation patches `fetch` — avoids a cold-cache model-load failure under OTEL
72
69
  - Self-describing: `cyanheads_describe_entry` resolves this server's own name and tools from a static fallback record, consulted only when the remote catalog doesn't carry an entry for it
@@ -210,6 +207,10 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
210
207
  | `EMBEDDING_MODEL_ID` | Hugging Face model id for query embedding. Must match `fleet.json.embeddingModel`. | `Snowflake/snowflake-arctic-embed-m-v1.5` |
211
208
  | `SIMILARITY_FLOOR` | Cosine similarity cutoff for `cyanheads_search_catalog` results. Must be within `[0, 1]`. | `0.3` |
212
209
  | `OTEL_ENABLED` | Enable OpenTelemetry | `false` |
210
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP base URL for traces and metrics | Unset |
211
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Explicit OTLP logs URL; requires the OTel log peers included in the default Docker build | Unset |
212
+ | `LOG_TOOL_FAILURE_PAYLOADS` | Log failed arguments and results, redacted by key name. Secrets inside free-form values are not redacted. | `false` |
213
+ | `LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES` | UTF-8 byte cap for each logged failure payload | `16384` |
213
214
 
214
215
  See [`.env.example`](./.env.example) for the full list of optional overrides.
215
216
 
@@ -0,0 +1,34 @@
1
+ ---
2
+ summary: "Catalog integrity fixes, complete search pagination, and client-specific installation guidance for every entry."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.3 — 2026-09-30
8
+
9
+ ## Changed
10
+
11
+ - **Docker builds** install target-platform dependencies on the native builder with Bun `1.4.0 → 1.4.2`; OpenTelemetry peers use the framework's tested ranges, security scanner, and release-age policy. Runtime logging follows framework configuration.
12
+ - **Development tooling** synchronizes framework skills and checks for definition import failures, bundle/version alignment, Docker build platforms, skill versions, and release annotations. Publishing uses a gated release PR.
13
+ - **Documentation and packaging** describe current catalog behavior, failure-payload logging, and OTLP logs configuration; correct the VS Code install link and exclude runtime logs and nested bundles from distribution artifacts.
14
+
15
+ ## Fixed
16
+
17
+ - **Search queries** reject whitespace-only input before embedding and trim valid queries for embedding and echo, retaining the 500-character raw limit. ([#12](https://github.com/cyanheads/cyanheads-mcp-server/issues/12))
18
+ - **Search continuation** exposes independent result and server roll-up offsets, full totals, and nullable next offsets. Reuse the query and filters; pages reflect the current catalog. ([#13](https://github.com/cyanheads/cyanheads-mcp-server/issues/13))
19
+ - **Catalog normalization** collapses identical exact-name duplicates before indexing and rejects conflicting records; search, descriptions, counts, and vectors share the normalized inventory. ([#14](https://github.com/cyanheads/cyanheads-mcp-server/issues/14))
20
+ - **Literal rendering** preserves descriptions, identifiers, metadata, and install payloads through Markdown rendering with delimiter-sized code spans and blocks. ([#15](https://github.com/cyanheads/cyanheads-mcp-server/issues/15))
21
+ - **Tool installation handoffs** include owning-server connection metadata and client-filtered snippets. Local-only curl requests return actionable stdio guidance, with required environment variables visible even when no snippet applies. ([#16](https://github.com/cyanheads/cyanheads-mcp-server/issues/16))
22
+ - **Empty catalogs** fail startup validation and retain the previous index on refresh; nonempty catalogs with zero-tool servers remain valid. ([#17](https://github.com/cyanheads/cyanheads-mcp-server/issues/17))
23
+ - **Name resolution** prefers exact remote names, then unique case-insensitive matches, and returns canonical names. Ambiguous folds remain unresolved; remote entries take precedence over self records. ([#20](https://github.com/cyanheads/cyanheads-mcp-server/issues/20))
24
+ - **Error recovery** uses framework-populated contract hints for handler and service failures, including retryable `catalog_empty` responses.
25
+
26
+ ## Dependencies
27
+
28
+ - `@cyanheads/mcp-ts-core` `^0.13.6 → ^0.13.10`.
29
+ - `@socketsecurity/bun-security-scanner` `^1.1.2 → ^1.1.3`.
30
+ - `@types/node` `^26.6.1 → ^26.6.3`.
31
+ - `@vitest/coverage-istanbul` `5.0.1 → 5.0.2`.
32
+ - `fast-check` `4.10.1 → 4.10.2`.
33
+ - `ignore` `^7.0.9 → ^7.0.10`.
34
+ - `vitest` `^5.0.1 → ^5.0.2`.
package/dist/index.js CHANGED
@@ -27,7 +27,9 @@ await createApp({
27
27
  prompts: [],
28
28
  instructions: 'This server is the discovery front door to the cyanheads MCP fleet. ' +
29
29
  'Use cyanheads_search_catalog to find tools or servers by describing what you want to do. ' +
30
- 'Use cyanheads_describe_entry to get full schemas and per-client install snippets for any result. ' +
30
+ 'Use cyanheads_describe_entry to get descriptions, connection metadata, and per-client install snippets for any result. ' +
31
+ 'Tool schemas are available from the connected server through tools/list. ' +
32
+ 'Continue searches with nextOffset and, in tools scope, nextServersOffset; reuse the same query and filters. ' +
31
33
  'Scope "tools" (default) finds individual tools; scope "servers" finds which server owns a workflow. ' +
32
34
  'cyanheads_describe_entry also resolves this server itself, under the name "cyanheads-mcp-server".',
33
35
  async setup() {
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,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,sBAAsB;IAC7B;;;;;;;;OAQG;IACH,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC7C,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE;IACX,YAAY,EACV,sEAAsE;QACtE,2FAA2F;QAC3F,mGAAmG;QACnG,sGAAsG;QACtG,mGAAmG;IAErG,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,iBAAiB,EAAE,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACN,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;CACF,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,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,sBAAsB;IAC7B;;;;;;;;OAQG;IACH,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC7C,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE;IACX,YAAY,EACV,sEAAsE;QACtE,2FAA2F;QAC3F,yHAAyH;QACzH,2EAA2E;QAC3E,8GAA8G;QAC9G,sGAAsG;QACtG,mGAAmG;IAErG,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,iBAAiB,EAAE,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACN,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;CACF,CAAC,CAAC"}
@@ -27,6 +27,28 @@ export declare const describeEntryTool: import("@cyanheads/mcp-ts-core").ToolDef
27
27
  name: z.ZodString;
28
28
  description: z.ZodString;
29
29
  server: z.ZodString;
30
+ npm: z.ZodString;
31
+ github: z.ZodString;
32
+ endpoint: z.ZodOptional<z.ZodString>;
33
+ auth: z.ZodString;
34
+ requiredEnvVars: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
+ installNotice: z.ZodOptional<z.ZodString>;
36
+ installSnippets: z.ZodArray<z.ZodObject<{
37
+ client: z.ZodEnum<{
38
+ "claude-code": "claude-code";
39
+ codex: "codex";
40
+ curl: "curl";
41
+ cursor: "cursor";
42
+ gemini: "gemini";
43
+ "streamable-http": "streamable-http";
44
+ }>;
45
+ transport: z.ZodEnum<{
46
+ http: "http";
47
+ stdio: "stdio";
48
+ }>;
49
+ label: z.ZodString;
50
+ payload: z.ZodString;
51
+ }, z.core.$strip>>;
30
52
  }, z.core.$strip>, z.ZodObject<{
31
53
  kind: z.ZodLiteral<"server">;
32
54
  name: z.ZodString;
@@ -38,6 +60,7 @@ export declare const describeEntryTool: import("@cyanheads/mcp-ts-core").ToolDef
38
60
  endpoint: z.ZodOptional<z.ZodString>;
39
61
  auth: z.ZodString;
40
62
  requiredEnvVars: z.ZodOptional<z.ZodArray<z.ZodString>>;
63
+ installNotice: z.ZodOptional<z.ZodString>;
41
64
  toolCount: z.ZodNumber;
42
65
  tools: z.ZodArray<z.ZodObject<{
43
66
  name: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"describe-entry.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/describe-entry.tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAYjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoS5B,CAAC"}
1
+ {"version":3,"file":"describe-entry.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/describe-entry.tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAajE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqT5B,CAAC"}