{"record":{"id":"cb9f8c5a56766593","repo":"langflow-ai/langflow","slug":"failed-to-install-mcp-cb9f8c","errorCode":null,"errorMessage":"Failed to install MCP","messagePattern":"Failed to install MCP","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/frontend/src/controllers/API/queries/mcp/use-patch-install-mcp.ts","lineNumber":41,"sourceCode":"export const usePatchInstallMCP: useMutationFunctionType<\n  PatchInstallMCPParams,\n  PatchInstallMCPBody,\n  PatchInstallMCPResponse\n> = (params, options?) => {\n  const { mutate, queryClient } = UseRequestProcessor();\n\n  async function patchInstallMCP(\n    body: PatchInstallMCPBody,\n  ): Promise<PatchInstallMCPResponse> {\n    try {\n      const res = await api.post(\n        `${getURL(\"MCP\")}/${params.project_id}/install`,\n        body,\n      );\n\n      return { message: res.data?.message || \"MCP installed successfully\" };\n    } catch (error: unknown) {\n      throw new Error(\n        extractApiErrorMessage(\n          error as Parameters<typeof extractApiErrorMessage>[0],\n          \"Failed to install MCP\",\n        ),\n      );\n    }\n  }\n\n  const mutation: UseMutationResult<\n    PatchInstallMCPResponse,\n    any,\n    PatchInstallMCPBody\n  > = mutate([\"usePatchInstallMCP\", params.project_id], patchInstallMCP, {\n    ...options,\n    onSuccess: (data, variables, context) => {\n      queryClient.invalidateQueries({\n        queryKey: [\"useGetInstalledMCP\", params.project_id],\n      });","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/frontend/src/controllers/API/queries/mcp/use-patch-install-mcp.ts#L23-L59","documentation":"400 from the install endpoint validating the transport field: after lowercasing, body.transport must be 'sse' or 'streamablehttp'. This is the only request-validation error in the flow and depends purely on the payload.","triggerScenarios":"POST /{project_id}/install with transport='streamable-http', 'HTTP', 'websocket', or any other string; omitting transport is safe because the default is 'sse'.","commonSituations":"Hand-crafted curl requests using the hyphenated form 'streamable-http'; older clients using 'streamable_http' with an underscore.","solutions":["Send transport: \"sse\" or transport: \"streamablehttp\" (no separator).","Omit the field entirely if SSE is acceptable.","Update any scripts that copied the hyphenated spelling from docs or URLs."],"exampleFix":"// before\n{\"client\": \"cursor\", \"transport\": \"streamable-http\"}\n// after\n{\"client\": \"cursor\", \"transport\": \"streamablehttp\"}","handlingStrategy":"validation","validationCode":"VALID_TRANSPORTS = {\"sse\", \"streamablehttp\"}\ntransport = (body.get(\"transport\") or \"sse\").lower()\nif transport not in VALID_TRANSPORTS:\n    body[\"transport\"] = \"sse\"  # or reject client-side with a clear message","typeGuard":"def is_valid_transport(t: str | None) -> bool:\n    return (t or \"sse\").lower() in {\"sse\", \"streamablehttp\"}","tryCatchPattern":null,"preventionTips":["Use the exact tokens 'sse' / 'streamablehttp' — no hyphen, no underscore.","Omit transport when SSE is fine; the default is applied server-side."],"tags":["mcp","install","validation","http-400"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}