Repository navigation
Refine MCP search output and embeddings - #115
Conversation
Co-authored-by: me <me@kentcdodds.com>
Co-authored-by: me <me@kentcdodds.com>
📝 WalkthroughWalkthroughAdds POST /__maintenance/reindex-apps and its handler to re-embed visible saved UI artifacts (excluding source code) and upsert Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Worker
participant DB
participant AI as AI_Embed_Model
participant Vector as VectorIndex
Client->>Worker: POST /__maintenance/reindex-apps + Bearer token
Worker->>Worker: validate CAPABILITY_REINDEX_SECRET
alt not configured
Worker-->>Client: 503 Saved app reindex is not configured
else authorized
Worker->>DB: query visible ui_artifacts (grouped by user)
DB-->>Worker: ui artifacts per user
Worker->>DB: list app secrets for appIds per user
DB-->>Worker: app secrets map
loop batches of artifacts
Worker->>AI_Embed_Model: run embedding for batch texts
AI_Embed_Model-->>Worker: embeddings array
Worker->>Vector: upsert vectors (ui_artifact_<uuid>, metadata)
Vector-->>Worker: upsert ack
end
Worker-->>Client: 200 { ok: true, upserted: N }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-authored-by: me <me@kentcdodds.com>
|
🔎 Preview deployed: https://kody-pr-115.kentcdodds.workers.dev Worker: Mocks:
|
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/worker/src/mcp/capabilities/unified-search.workers.test.ts (1)
57-63:⚠️ Potential issue | 🔴 CriticalRemove the stale
detailargument from this test call.Line 62 still passes
detail: false, butsearchUnifiedno longer accepts that property. This object literal should failnpm run typecheck.Suggested fix
const result = await searchUnified({ env, baseUrl: 'http://localhost', query: 'open pull requests for cursor agents', limit: 5, - detail: false, specs, userId: 'user-123', skillRows: [skillRow],🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/worker/src/mcp/capabilities/unified-search.workers.test.ts` around lines 57 - 63, The test calls searchUnified with a stale property; remove the no-longer-supported detail field from the object passed to searchUnified (the call where result is assigned) so the argument object matches the current searchUnified signature; update the invocation that includes env, baseUrl, query, limit, and specs to omit detail entirely.
🧹 Nitpick comments (1)
packages/worker/src/mcp/ui-artifact-reindex.ts (1)
13-25: Avoid the per-user D1 fan-out in the full reindex job.Lines 13-25 fetch distinct users and then reload artifacts per user, and Lines 44-66 do another secrets lookup per user. On a large saved-app corpus that is
2 * users + 1DB round-trips plus full in-memory materialization before embedding work, which is a risky shape for a deploy-time Worker task. A paginated scan of visible apps with batched secret lookups by app id would scale much better.Also applies to: 44-66
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/setup-manifest.md`:
- Line 93: Replace the single word "builtin" with the hyphenated form "built-in"
in the sentence that mentions the endpoint `POST /__maintenance/reindex-apps` so
it reads "built-in capabilities"; update the phrase near that endpoint reference
(`POST /__maintenance/reindex-apps`) accordingly to use "built-in".
In `@packages/worker/src/mcp/skills/skill-embed-and-flags.ts`:
- Around line 61-63: Filter inferred capability names using an own-property
check and remove duplicates: replace the current filter on
input.inferredCapabilities that uses input.specs[name] != null with a check
using Object.prototype.hasOwnProperty.call(input.specs, name) to ensure only own
keys of input.specs are accepted, deduplicate the list (e.g., via a Set) and
then sort it; refer to inferredCapabilityNames, input.inferredCapabilities,
input.specs and the existing mergeInferredCapabilityNames pattern for
consistency.
In `@packages/worker/src/mcp/tools/search-format.ts`:
- Around line 42-49: The new slim app shape dropped the app-bound secret
metadata: update the app result shape (the object with type: 'app' that
currently lists id, title, description, usage, hostedUrl) to include the
availableSecrets field and ensure every place that maps search hits into that
shape (including searchUnified result mapping and the markdown renderers that
build app outputs) copies availableSecrets from the original hit into the new
shape; apply the same addition to the other mapping sites you noted (lines
~90-101, ~211-230, ~239-275, ~412-451) so ranked results and entity: "...:app"
details continue to expose the app's availableSecrets.
In `@packages/worker/src/mcp/tools/search.ts`:
- Around line 330-333: The code is using the best-effort list
input.searchRows.userSecretRows to resolve an exact secret (ref.id), which hides
transient loader failures from loadOptionalSearchRows; instead replace this
lookup with a direct fetch (call the secret loader / fetch-by-name function
rather than searching userSecretRows) or detect and rethrow the loader error
produced by loadOptionalSearchRows so we don’t convert backend failures into
"Secret not found for this user."; update the branch around the lookups that
reference input.searchRows.userSecretRows and the thrown message "Secret not
found for this user." to use a direct secret-by-name fetch or propagate the
original loader error.
In `@packages/worker/src/mcp/ui-artifact-reindex.ts`:
- Around line 39-42: The current reindex only calls listAllVisibleUiArtifacts
and upserts visible items (see listAllVisibleUiArtifacts and the upsert loop
around lines 94-104), so stale vector rows named like ui_artifact_<uuid> for
hidden/deleted apps are never removed; modify the routine to perform a delete
phase: either (A) fetch existing vector IDs from the vector store (matching
prefix ui_artifact_), compute the set difference against the visible rows
returned by listAllVisibleUiArtifacts, and delete those stale ids before/after
upserting, or (B) perform a full rebuild by removing all ui_artifact_* vectors
first and then upserting the current visible rows—implement the chosen strategy
and ensure the code references listAllVisibleUiArtifacts, the upsert logic, and
the vector-store delete operation so stale vectors are removed.
In `@packages/worker/src/mcp/ui-artifacts-embed.node.test.ts`:
- Around line 4-26: The test "buildUiArtifactEmbedText excludes source code and
keeps parameter hints" is passing a stale code property that no longer exists on
buildUiArtifactEmbedText's input type; remove the code: '<main>…</main>' field
from the test payload so the object matches the current input shape for
buildUiArtifactEmbedText, leaving title, description, runtime and parameters
as-is (keep assertions unchanged), and if you still want to assert that source
code is never embedded move that coverage to the ui_save_app or reindex call
sites that still accept a code field.
---
Outside diff comments:
In `@packages/worker/src/mcp/capabilities/unified-search.workers.test.ts`:
- Around line 57-63: The test calls searchUnified with a stale property; remove
the no-longer-supported detail field from the object passed to searchUnified
(the call where result is assigned) so the argument object matches the current
searchUnified signature; update the invocation that includes env, baseUrl,
query, limit, and specs to omit detail entirely.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 06124774-80cb-4599-8106-f13e548569bb
📒 Files selected for processing (17)
docs/agents/mcp-skills.mddocs/setup-manifest.mdpackages/worker/src/index.tspackages/worker/src/mcp/capabilities/apps/ui-save-app.tspackages/worker/src/mcp/capabilities/unified-search.tspackages/worker/src/mcp/capabilities/unified-search.workers.test.tspackages/worker/src/mcp/index.tspackages/worker/src/mcp/mcp-server.mcp-e2e.test.tspackages/worker/src/mcp/skills/skill-embed-and-flags.node.test.tspackages/worker/src/mcp/skills/skill-embed-and-flags.tspackages/worker/src/mcp/tools/search-format.tspackages/worker/src/mcp/tools/search.tspackages/worker/src/mcp/ui-artifact-reindex.tspackages/worker/src/mcp/ui-artifacts-embed.node.test.tspackages/worker/src/mcp/ui-artifacts-embed.tspackages/worker/src/mcp/ui-artifacts-search.tspackages/worker/src/ui-artifact-maintenance.ts
💤 Files with no reviewable changes (2)
- packages/worker/src/mcp/capabilities/apps/ui-save-app.ts
- packages/worker/src/mcp/ui-artifacts-embed.ts
| and all user skills into Vectorize) | ||
| `POST /__maintenance/reindex-capabilities`, | ||
| `POST /__maintenance/reindex-skills`, and | ||
| `POST /__maintenance/reindex-apps` to embed and upsert builtin capabilities, |
There was a problem hiding this comment.
Use built-in here.
Line 93 reads more naturally as built-in capabilities.
🧰 Tools
🪛 LanguageTool
[grammar] ~93-~93: Ensure spelling is correct
Context: ...nance/reindex-apps` to embed and upsert builtin capabilities, all user skills, and di...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/setup-manifest.md` at line 93, Replace the single word "builtin" with
the hyphenated form "built-in" in the sentence that mentions the endpoint `POST
/__maintenance/reindex-apps` so it reads "built-in capabilities"; update the
phrase near that endpoint reference (`POST /__maintenance/reindex-apps`)
accordingly to use "built-in".
| const inferredCapabilityNames = input.inferredCapabilities | ||
| .filter((name) => input.specs[name] != null) | ||
| .sort() |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify current membership checks in this module.
rg -n -C2 "input\.specs\[name\]|hasOwnProperty|Object\.hasOwn" packages/worker/src/mcp/skills/skill-embed-and-flags.tsRepository: kentcdodds/kody
Length of output: 221
🏁 Script executed:
# Read the full context of the function containing this code
cat -n packages/worker/src/mcp/skills/skill-embed-and-flags.ts | head -100Repository: kentcdodds/kody
Length of output: 3690
🏁 Script executed:
# Check if input.specs could have prototype-inherited keys
# Search for where input is defined and its type
rg -n "input\s*[:=]|inferredCapabilities|specs" packages/worker/src/mcp/skills/skill-embed-and-flags.ts | head -30Repository: kentcdodds/kody
Length of output: 678
🏁 Script executed:
# Look for similar property access patterns in the codebase
rg -n "\[name\]\s*!=\s*null|\[.*\]\s*!=\s*undefined" packages/worker/src/mcp/skills/ | head -20Repository: kentcdodds/kody
Length of output: 164
🏁 Script executed:
# Check how specs and inferredCapabilities are created/sourced in the codebase
rg -n "inferredCapabilities\s*[:=]|specs\s*[:=]" packages/worker/src/mcp/skills/ --max-count=20Repository: kentcdodds/kody
Length of output: 1242
🏁 Script executed:
# Check if there are other places where input.specs[name] pattern is used
rg -n "\.specs\[" packages/worker/src/mcp/skills/skill-embed-and-flags.tsRepository: kentcdodds/kody
Length of output: 108
🏁 Script executed:
# Check the rest of the file to see deriveTrustFlags function fully
sed -n '79,115p' packages/worker/src/mcp/skills/skill-embed-and-flags.tsRepository: kentcdodds/kody
Length of output: 965
Use own-property checks when filtering inferred capability names.
At line 62, input.specs[name] != null can accept prototype-inherited keys (for example toString) as valid capability names, introducing bogus inferred capability tokens into embeddings. This inconsistency also appears alongside the safer Object.keys() pattern used in mergeInferredCapabilityNames in the same file. Use Object.prototype.hasOwnProperty.call(input.specs, name) to check only own properties, and deduplicate the input list:
Proposed fix
- const inferredCapabilityNames = input.inferredCapabilities
- .filter((name) => input.specs[name] != null)
- .sort()
+ const inferredCapabilityNames = [...new Set(input.inferredCapabilities)]
+ .filter((name) =>
+ Object.prototype.hasOwnProperty.call(input.specs, name),
+ )
+ .sort()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const inferredCapabilityNames = input.inferredCapabilities | |
| .filter((name) => input.specs[name] != null) | |
| .sort() | |
| const inferredCapabilityNames = [...new Set(input.inferredCapabilities)] | |
| .filter((name) => | |
| Object.prototype.hasOwnProperty.call(input.specs, name), | |
| ) | |
| .sort() |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/worker/src/mcp/skills/skill-embed-and-flags.ts` around lines 61 -
63, Filter inferred capability names using an own-property check and remove
duplicates: replace the current filter on input.inferredCapabilities that uses
input.specs[name] != null with a check using
Object.prototype.hasOwnProperty.call(input.specs, name) to ensure only own keys
of input.specs are accepted, deduplicate the list (e.g., via a Set) and then
sort it; refer to inferredCapabilityNames, input.inferredCapabilities,
input.specs and the existing mergeInferredCapabilityNames pattern for
consistency.
| | { | ||
| type: 'app' | ||
| id: string | ||
| title: string | ||
| description: string | ||
| usage: string | ||
| hostedUrl: string | ||
| } |
There was a problem hiding this comment.
Preserve app-bound secret metadata in the new search output.
searchUnified still attaches availableSecrets to app hits, but the new slim app shapes and markdown renderers drop that field completely here. After this change, neither ranked search results nor entity: "...:app" detail tells callers which app secrets exist, which regresses the "nest app secrets on apps" behavior and makes saved-app discovery less useful.
Also applies to: 90-101, 211-230, 239-275, 412-451
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/worker/src/mcp/tools/search-format.ts` around lines 42 - 49, The new
slim app shape dropped the app-bound secret metadata: update the app result
shape (the object with type: 'app' that currently lists id, title, description,
usage, hostedUrl) to include the availableSecrets field and ensure every place
that maps search hits into that shape (including searchUnified result mapping
and the markdown renderers that build app outputs) copies availableSecrets from
the original hit into the new shape; apply the same addition to the other
mapping sites you noted (lines ~90-101, ~211-230, ~239-275, ~412-451) so ranked
results and entity: "...:app" details continue to expose the app's
availableSecrets.
| const row = input.searchRows.userSecretRows.find((secret) => secret.name === ref.id) | ||
| if (!row) { | ||
| throw new Error('Secret not found for this user.') | ||
| } |
There was a problem hiding this comment.
Don't resolve exact secret entities from the best-effort search list.
This branch depends on searchRows.userSecretRows, but loadOptionalSearchRows(...) intentionally downgrades secret-loader failures into warnings. In that case, Line 331 throws "Secret not found for this user." for a transient backend failure instead of surfacing the real problem. Exact entity: "...:secret" lookups should fetch directly by name or propagate the loader error.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/worker/src/mcp/tools/search.ts` around lines 330 - 333, The code is
using the best-effort list input.searchRows.userSecretRows to resolve an exact
secret (ref.id), which hides transient loader failures from
loadOptionalSearchRows; instead replace this lookup with a direct fetch (call
the secret loader / fetch-by-name function rather than searching userSecretRows)
or detect and rethrow the loader error produced by loadOptionalSearchRows so we
don’t convert backend failures into "Secret not found for this user."; update
the branch around the lookups that reference input.searchRows.userSecretRows and
the thrown message "Secret not found for this user." to use a direct
secret-by-name fetch or propagate the original loader error.
| const rows = await listAllVisibleUiArtifacts(env) | ||
| if (rows.length === 0) { | ||
| return { upserted: 0 } | ||
| } |
There was a problem hiding this comment.
This reindex path never removes stale app vectors.
Because it only scans hidden = 0 rows and then calls upsert, any ui_artifact_<uuid> already left behind for a now-hidden or deleted app survives this maintenance run. That means the endpoint cannot fully repair D1/Vectorize drift; it needs a delete phase or rebuild strategy for ids that are no longer visible.
Also applies to: 94-104
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/worker/src/mcp/ui-artifact-reindex.ts` around lines 39 - 42, The
current reindex only calls listAllVisibleUiArtifacts and upserts visible items
(see listAllVisibleUiArtifacts and the upsert loop around lines 94-104), so
stale vector rows named like ui_artifact_<uuid> for hidden/deleted apps are
never removed; modify the routine to perform a delete phase: either (A) fetch
existing vector IDs from the vector store (matching prefix ui_artifact_),
compute the set difference against the visible rows returned by
listAllVisibleUiArtifacts, and delete those stale ids before/after upserting, or
(B) perform a full rebuild by removing all ui_artifact_* vectors first and then
upserting the current visible rows—implement the chosen strategy and ensure the
code references listAllVisibleUiArtifacts, the upsert logic, and the
vector-store delete operation so stale vectors are removed.
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/worker/src/mcp/capabilities/unified-search.ts (1)
361-366:⚠️ Potential issue | 🟡 MinorKeep a description on capability summary hits.
Line 365 forces
searchCapabilitiesonto the summary row. The summary shape inpackages/worker/src/mcp/capabilities/capability-search.tsomitsdescription, andpackages/worker/src/mcp/tools/search-format.tsfalls back to an empty string when that field is missing. The new compact search output will therefore render builtin capability matches without descriptions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/worker/src/mcp/capabilities/unified-search.ts` around lines 361 - 366, searchCapabilities is being called with detail: false in unified-search.ts which returns the compact summary shape (from capability-search.ts) that omits description, causing search-format.ts to fall back to an empty string for builtin capabilities; change the call to searchCapabilities({ ..., detail: true, ... }) so the returned hits include the description field, or otherwise ensure the summary includes description by requesting the detailed shape in unified-search.ts (referencing searchCapabilities, capability-search.ts, and search-format.ts).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/worker/src/mcp/capabilities/unified-search.ts`:
- Around line 361-366: searchCapabilities is being called with detail: false in
unified-search.ts which returns the compact summary shape (from
capability-search.ts) that omits description, causing search-format.ts to fall
back to an empty string for builtin capabilities; change the call to
searchCapabilities({ ..., detail: true, ... }) so the returned hits include the
description field, or otherwise ensure the summary includes description by
requesting the detailed shape in unified-search.ts (referencing
searchCapabilities, capability-search.ts, and search-format.ts).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: bcb3e4d3-f2f9-4480-a9b1-f1ba803f3f39
📒 Files selected for processing (1)
packages/worker/src/mcp/capabilities/unified-search.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/worker/src/mcp/capabilities/capability-search.ts (2)
143-145: Redundantdescriptionassignment intoDetail.
toSummary(spec)now returnsdescription, so the explicitdescription: spec.descriptionon line 145 overwrites the same value. Safe to remove.♻️ Proposed cleanup
const row: CapabilityDetailRow = { ...toSummary(spec), - description: spec.description, keywords: spec.keywords,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/worker/src/mcp/capabilities/capability-search.ts` around lines 143 - 145, The toDetail function constructs a CapabilityDetailRow by spreading toSummary(spec) which already includes description; remove the redundant explicit assignment description: spec.description from the object literal in toDetail so the description from toSummary(spec) is not overwritten and behavior remains the same (update the object in toDetail that builds CapabilityDetailRow, referencing toSummary and spec).
106-116: Consider removing redundantdescriptionfromCapabilityDetailRow.Since
CapabilitySummaryRownow includesdescription, the explicitdescription: stringdeclaration inCapabilityDetailRow(line 107) is redundant—it's already inherited via the&intersection.♻️ Proposed cleanup
export type CapabilityDetailRow = CapabilitySummaryRow & { - description: string keywords: Array<string> readOnly: boolean idempotent: boolean🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/worker/src/mcp/capabilities/capability-search.ts` around lines 106 - 116, CapabilityDetailRow redundantly redeclares description already provided by CapabilitySummaryRow; remove the explicit "description: string" property from the CapabilityDetailRow type declaration so it simply extends CapabilitySummaryRow (& { keywords: Array<string>; readOnly: boolean; idempotent: boolean; destructive: boolean; inputSchema: unknown; outputSchema?: unknown; inputFields?: Array<string>; outputFields?: Array<string> }) and run type checks to ensure no other code expects the duplicate declaration.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/worker/src/mcp/capabilities/capability-search.ts`:
- Around line 143-145: The toDetail function constructs a CapabilityDetailRow by
spreading toSummary(spec) which already includes description; remove the
redundant explicit assignment description: spec.description from the object
literal in toDetail so the description from toSummary(spec) is not overwritten
and behavior remains the same (update the object in toDetail that builds
CapabilityDetailRow, referencing toSummary and spec).
- Around line 106-116: CapabilityDetailRow redundantly redeclares description
already provided by CapabilitySummaryRow; remove the explicit "description:
string" property from the CapabilityDetailRow type declaration so it simply
extends CapabilitySummaryRow (& { keywords: Array<string>; readOnly: boolean;
idempotent: boolean; destructive: boolean; inputSchema: unknown; outputSchema?:
unknown; inputFields?: Array<string>; outputFields?: Array<string> }) and run
type checks to ensure no other code expects the duplicate declaration.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7325f6ce-dcd0-42b5-bcfb-ce68219533aa
📒 Files selected for processing (1)
packages/worker/src/mcp/capabilities/capability-search.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
| return [`## Skill — ${match.title}`, '', match.description] | ||
| } | ||
| if (match.type === 'app') { | ||
| const hostedUrl = buildSavedUiUrl(baseUrl, match.appId) |
There was a problem hiding this comment.
Redundant hostedUrl recomputation ignores existing match field
Low Severity
Both formatMatchBlock and toSlimStructuredMatches call buildSavedUiUrl(baseUrl, match.appId) to compute the hosted URL, but after narrowing match.type === 'app', the UiArtifactSearchHit already carries a pre-computed hostedUrl field. Using match.hostedUrl directly would avoid the redundant computation and reduce coupling to buildSavedUiUrl in these formatting functions.
Additional Locations (1)
Co-authored-by: me <me@kentcdodds.com>


Summary
searchdetail payloads with compact markdown plus slim structured results and exact entity lookupsnpm run typecheckpasses againTesting
npm run typechecknpm run buildnpm run test -- packages/worker/src/mcp/skills/skill-embed-and-flags.node.test.ts packages/worker/src/mcp/ui-artifacts-embed.node.test.ts packages/worker/src/mcp/capabilities/unified-search.workers.test.ts packages/worker/src/mcp/tools/search.node.test.tsnpm run test:mcp -- packages/worker/src/mcp/mcp-server.mcp-e2e.test.tsSummary by CodeRabbit
New Features
Changes