From 78cf402141ce8f07622fc6cefa88622e981b89d9 Mon Sep 17 00:00:00 2001 From: Marsssssssssssdsss Date: Mon, 1 Jun 2026 17:56:42 +0800 Subject: [PATCH] fix: handle empty results in MCP keyword_search tool (#15058) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixes: #15038 — MCP keyword_search tool errors with "Unexpected response type" when no results are found. ### Problem When the MCP `keyword_search` tool returns no matching documents, the access control `.docs()` method may return `undefined`/`null` for an empty input array. Calling `.map()` on this value throws an error, and the MCP framework wraps it as "Unexpected response type". ### Solution Added a guard check after the permission filtering step. If the result is empty or null, the tool now returns a proper informational response instead of throwing. ### Changes - `packages/backend/server/src/plugins/copilot/mcp/provider.ts`: Added null/empty check before `docs.map()` in the keyword_search tool execute function. ### Testing - **Before**: `keyword_search` with a non-existent keyword throws "Unexpected response type" - **After**: `keyword_search` with a non-existent keyword returns `{ content: [{ type: 'text', text: 'No matching documents found.' }] }` ## Summary by CodeRabbit * **Bug Fixes** * Prevented errors when document data is missing, improving search stability. * Improved search feedback by displaying a clear "No matching documents found." message instead of empty results. --- .../server/src/plugins/copilot/mcp/provider.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/backend/server/src/plugins/copilot/mcp/provider.ts b/packages/backend/server/src/plugins/copilot/mcp/provider.ts index 3551704700..8ed8bcb191 100644 --- a/packages/backend/server/src/plugins/copilot/mcp/provider.ts +++ b/packages/backend/server/src/plugins/copilot/mcp/provider.ts @@ -191,10 +191,10 @@ export class WorkspaceMcpProvider { if (abortedAfterDocs) return abortedAfterDocs; return { - content: docs.map(doc => ({ + content: (docs?.map(doc => ({ type: 'text', text: clearEmbeddingChunk(doc).content, - })), + })) ?? []), }; }, }); @@ -230,11 +230,15 @@ export class WorkspaceMcpProvider { const abortedAfterDocs = abortIfNeeded(options.signal); if (abortedAfterDocs) return abortedAfterDocs; + if (!docs || docs.length === 0) { + return toolText('No matching documents found.'); + } + return { - content: docs.map(doc => ({ + content: (docs?.map(doc => ({ type: 'text', text: JSON.stringify(pick(doc, 'docId', 'title', 'createdAt')), - })), + })) ?? []), }; }, });