From 37d87933b6742900eda4f0aff7fc5d40215ddada Mon Sep 17 00:00:00 2001 From: "a.dmitriev" Date: Sun, 26 Apr 2026 15:36:28 +0200 Subject: [PATCH 1/2] fix(mcp): match language model by provider+model with precise error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MCP package (@sourcebot/mcp) omits displayName from the ask_codebase request schema (.omit({ displayName: true })), so LLM agents can only pass {provider, model}. The previous getLanguageModelKey-based match included displayName in the key, causing a permanent 400 for any explicit model selection. New matching logic: - filter configured models by provider+model to collect candidates - displayName check uses !== undefined (not truthiness) so "" is treated as an explicit value, not absent - if displayName provided: exact match within candidates — preserves disambiguation between same-model entries with different displayName (e.g. two opus-4-7 with different reasoningEffort) - if displayName absent and exactly one candidate: use it - if displayName absent and multiple candidates: return 400 with hint Three distinct 400 messages: - provider+model not found: "Language model 'X/Y' is not configured." - displayName mismatch: "… is configured but displayName 'Z' was not found. Available: "A", "B"." - ambiguous: "Multiple configurations found for 'X/Y'. Provide a displayName to disambiguate. Available: "A", "B"." Available displayNames are quoted and filtered so undefined values never appear in error messages. Also removes the now-unused getLanguageModelKey import. Fixes #1137 --- packages/web/src/features/mcp/askCodebase.ts | 28 +++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/web/src/features/mcp/askCodebase.ts b/packages/web/src/features/mcp/askCodebase.ts index 6451e680f..00efcc0ba 100644 --- a/packages/web/src/features/mcp/askCodebase.ts +++ b/packages/web/src/features/mcp/askCodebase.ts @@ -1,7 +1,7 @@ import { sew } from "@/middleware/sew"; import { getConfiguredLanguageModels, getAISDKLanguageModelAndOptions, generateChatNameFromMessage, updateChatMessages } from "@/features/chat/utils.server"; import { LanguageModelInfo, SBChatMessage, SearchScope } from "@/features/chat/types"; -import { convertLLMOutputToPortableMarkdown, getAnswerPartFromAssistantMessage, getLanguageModelKey } from "@/features/chat/utils"; +import { convertLLMOutputToPortableMarkdown, getAnswerPartFromAssistantMessage } from "@/features/chat/utils"; import { ErrorCode } from "@/lib/errorCodes"; import { ServiceError, ServiceErrorException } from "@/lib/serviceError"; import { withOptionalAuth } from "@/middleware/withAuth"; @@ -57,14 +57,34 @@ export const askCodebase = (params: AskCodebaseParams): Promise getLanguageModelKey(m) === getLanguageModelKey(requestedLanguageModel) + const candidates = configuredModels.filter( + (m) => m.provider === requestedLanguageModel.provider && + m.model === requestedLanguageModel.model ); + const displayNameProvided = requestedLanguageModel.displayName !== undefined; + const matchingModel = displayNameProvided + ? candidates.find((m) => m.displayName === requestedLanguageModel.displayName) + : candidates.length === 1 ? candidates[0] : undefined; if (!matchingModel) { + const available = candidates + .map((m) => m.displayName) + .filter((n): n is string => n !== undefined) + .map((n) => `"${n}"`) + .join(', '); + let message: string; + if (candidates.length === 0) { + message = `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is not configured.`; + } else if (displayNameProvided) { + message = `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is configured but displayName '${requestedLanguageModel.displayName}' was not found.` + + (available ? ` Available: ${available}.` : ''); + } else { + message = `Multiple configurations found for '${requestedLanguageModel.provider}/${requestedLanguageModel.model}'. Provide a displayName to disambiguate.` + + (available ? ` Available: ${available}.` : ''); + } return { statusCode: StatusCodes.BAD_REQUEST, errorCode: ErrorCode.INVALID_REQUEST_BODY, - message: `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is not configured.`, + message, } satisfies ServiceError; } languageModelConfig = matchingModel; From 2ce84cdcfc2ffc3ef050a7510b4860a7b1cc86db Mon Sep 17 00:00:00 2001 From: "a.dmitriev" Date: Sun, 26 Apr 2026 15:39:05 +0200 Subject: [PATCH 2/2] fix(mcp): actionable error when all ambiguous candidates lack displayName --- packages/web/src/features/mcp/askCodebase.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/web/src/features/mcp/askCodebase.ts b/packages/web/src/features/mcp/askCodebase.ts index 00efcc0ba..4ec5b2e90 100644 --- a/packages/web/src/features/mcp/askCodebase.ts +++ b/packages/web/src/features/mcp/askCodebase.ts @@ -78,8 +78,9 @@ export const askCodebase = (params: AskCodebaseParams): Promise