Skip to content

Commit 37d8793

Browse files
author
a.dmitriev
committed
fix(mcp): match language model by provider+model with precise error messages
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
1 parent 105ddf4 commit 37d8793

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

packages/web/src/features/mcp/askCodebase.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { sew } from "@/middleware/sew";
22
import { getConfiguredLanguageModels, getAISDKLanguageModelAndOptions, generateChatNameFromMessage, updateChatMessages } from "@/features/chat/utils.server";
33
import { LanguageModelInfo, SBChatMessage, SearchScope } from "@/features/chat/types";
4-
import { convertLLMOutputToPortableMarkdown, getAnswerPartFromAssistantMessage, getLanguageModelKey } from "@/features/chat/utils";
4+
import { convertLLMOutputToPortableMarkdown, getAnswerPartFromAssistantMessage } from "@/features/chat/utils";
55
import { ErrorCode } from "@/lib/errorCodes";
66
import { ServiceError, ServiceErrorException } from "@/lib/serviceError";
77
import { withOptionalAuth } from "@/middleware/withAuth";
@@ -57,14 +57,34 @@ export const askCodebase = (params: AskCodebaseParams): Promise<AskCodebaseResul
5757

5858
let languageModelConfig = configuredModels[0];
5959
if (requestedLanguageModel) {
60-
const matchingModel = configuredModels.find(
61-
(m) => getLanguageModelKey(m) === getLanguageModelKey(requestedLanguageModel)
60+
const candidates = configuredModels.filter(
61+
(m) => m.provider === requestedLanguageModel.provider &&
62+
m.model === requestedLanguageModel.model
6263
);
64+
const displayNameProvided = requestedLanguageModel.displayName !== undefined;
65+
const matchingModel = displayNameProvided
66+
? candidates.find((m) => m.displayName === requestedLanguageModel.displayName)
67+
: candidates.length === 1 ? candidates[0] : undefined;
6368
if (!matchingModel) {
69+
const available = candidates
70+
.map((m) => m.displayName)
71+
.filter((n): n is string => n !== undefined)
72+
.map((n) => `"${n}"`)
73+
.join(', ');
74+
let message: string;
75+
if (candidates.length === 0) {
76+
message = `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is not configured.`;
77+
} else if (displayNameProvided) {
78+
message = `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is configured but displayName '${requestedLanguageModel.displayName}' was not found.`
79+
+ (available ? ` Available: ${available}.` : '');
80+
} else {
81+
message = `Multiple configurations found for '${requestedLanguageModel.provider}/${requestedLanguageModel.model}'. Provide a displayName to disambiguate.`
82+
+ (available ? ` Available: ${available}.` : '');
83+
}
6484
return {
6585
statusCode: StatusCodes.BAD_REQUEST,
6686
errorCode: ErrorCode.INVALID_REQUEST_BODY,
67-
message: `Language model '${requestedLanguageModel.provider}/${requestedLanguageModel.model}' is not configured.`,
87+
message,
6888
} satisfies ServiceError;
6989
}
7090
languageModelConfig = matchingModel;

0 commit comments

Comments
 (0)