Skip to content

fix(ui): honor LITELLM_UI_API_DOC_BASE_URL on the MCP Servers Connect and Toolsets tabs - #35587

Draft
bharatr21 wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
bharatr21:litellm_ui_mcp_connect_doc_base_url
Draft

fix(ui): honor LITELLM_UI_API_DOC_BASE_URL on the MCP Servers Connect and Toolsets tabs#35587
bharatr21 wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
bharatr21:litellm_ui_mcp_connect_doc_base_url

Conversation

@bharatr21

Copy link
Copy Markdown

TLDR

Problem this solves:

  • MCP Connect tab prints PROXY_BASE_URL, ignoring LITELLM_UI_API_DOC_BASE_URL
  • Toolset endpoint URLs on the sibling tab have the same bug
  • Users copy snippets pointing at the wrong host

How it solves it:

  • New useDocBaseUrl hook prefers a non-blank LITELLM_UI_API_DOC_BASE_URL
  • Falls back to getProxyBaseUrl(), so unset behaves exactly as today
  • Connect snippets and toolset URLs read that single resolved base

Relevant issues

Fixes #35583

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Steps to capture before/after, with PROXY_BASE_URL and LITELLM_UI_API_DOC_BASE_URL deliberately pointed at different hosts:

  1. Export both, then start the proxy: export PROXY_BASE_URL=http://localhost:4000 and export LITELLM_UI_API_DOC_BASE_URL=https://gateway.example.com, then python litellm/proxy/proxy_cli.py --config litellm/proxy/dev_config.yaml --detailed_debug --reload --use_v2_migration_resolver 2>&1 | tee litellm.log
  2. Start the dashboard with npm run dev in ui/litellm-dashboard
  3. Open http://localhost:4000/ui/?page=mcp-servers and click the Connect tab; screenshot the Server URL and the OpenAI / LiteLLM Proxy / Cursor / Streamable HTTP snippets. Before this PR they read http://localhost:4000/mcp; after, https://gateway.example.com/mcp
  4. Click the Toolsets tab; screenshot the "Claude Code / Cursor config" block and a toolset row's endpoint subtitle, then use the row's three-dot menu -> Copy endpoint URL and paste it. All three should show https://gateway.example.com/toolset/...
  5. Unset LITELLM_UI_API_DOC_BASE_URL, restart both, and repeat steps 3 and 4 to confirm everything reverts to http://localhost:4000

Type

🐛 Bug Fix

Changes

useDocBaseUrl lives at app/(dashboard)/hooks/proxySettings/useDocBaseUrl.ts next to useProxySettings. It exports a pure resolveDocBaseUrl(docBaseUrl, fallback) that trims and prefers the doc base, plus the hook that composes useAuthorized, useProxySettings and getProxyBaseUrl. Taking the fallback as a parameter keeps the trim-and-prefer semantics shareable without forcing one chain on every caller

Falling back to getProxyBaseUrl() rather than straight to PROXY_BASE_URL preserves the worker-url override in networking.tsx, so the only behavior change is the one the issue asks for

toolsetEndpointUrl now takes its base as a parameter because it is called from a TanStack column cell renderer where calling a hook is unsafe; the resolved base is injected through the existing MCPToolsetTableColumnsDeps object, matching how that file already receives its dependencies

chat_ui/CodeSnippets.tsx keeps its own inlined chain (LITELLM_UI_API_DOC_BASE_URL > PROXY_BASE_URL > window.location.origin). Those snippets are not worker-aware today and making them so is a separate change

Tests were written first and each was watched fail against the unfixed code: useDocBaseUrl.test.ts pins the resolution order and the blank/whitespace/null guards, mcp_connect.test.tsx asserts the rendered Server URL follows the doc base when set and the proxy base when not, MCPToolsetsTab.test.tsx covers the usage-guide snippet and the per-row endpoint URL, and the existing MCPToolsetTableColumns.test.tsx was updated to inject a doc base distinct from the mocked proxy base so an inverted priority fails it

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

… and Toolsets tabs

The Connect tab and the toolset endpoint URLs built every copy-paste snippet from
getProxyBaseUrl(), so an operator who sets LITELLM_UI_API_DOC_BASE_URL to the public
gateway URL still handed users the proxy base

Adds a useDocBaseUrl hook that prefers a non-blank LITELLM_UI_API_DOC_BASE_URL and falls
back to getProxyBaseUrl(), keeping today's behavior (including the worker-url override)
when the variable is unset. toolsetEndpointUrl now takes its base explicitly since it is
called from a column cell renderer where a hook is unsafe; the base is injected through
the existing MCPToolsetTableColumnsDeps

Fixes BerriAI#35583
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a shared documentation-base hook and applies it to MCP connection snippets and toolset endpoint displays and copy actions

  • Prefers LITELLM_UI_API_DOC_BASE_URL while retaining the existing proxy and worker-aware fallback
  • Injects the resolved base into TanStack table column renderers
  • Adds regression coverage for configured and unset documentation-base values
  • The resolver needs to return a normalized value before paths are appended

Confidence Score: 4/5

The URL normalization defect should be fixed before merging because valid environment formatting can produce unusable copied MCP endpoints

The new resolver checks a trimmed value but returns the raw configuration, and every changed consumer appends paths directly, allowing surrounding whitespace or a trailing slash to propagate into user-facing endpoint URLs

Files Needing Attention: ui/litellm-dashboard/src/app/(dashboard)/hooks/proxySettings/useDocBaseUrl.ts

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/app/(dashboard)/hooks/proxySettings/useDocBaseUrl.ts Adds the shared precedence resolver, but returns whitespace and trailing slashes unchanged despite checking a trimmed value
ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/mcp_connect.tsx Consistently switches MCP and Responses snippets to the resolved documentation base, while inheriting its normalization defect
ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/MCPToolsetsTab.tsx Uses the documentation base for the usage guide and injects it into table dependencies
ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/MCPToolsetTableColumns.tsx Correctly receives the base as a dependency for display and clipboard URLs, but directly appends paths to an unnormalized base
ui/litellm-dashboard/src/app/(dashboard)/hooks/proxySettings/useDocBaseUrl.test.ts Covers precedence and blank values but does not verify normalization of accepted values
ui/litellm-dashboard/src/app/(dashboard)/mcp-servers/_components/MCPToolsetsTab.test.tsx Covers configured and fallback URLs for both usage-guide and table output using clean base values

Reviews (1): Last reviewed commit: "fix(ui): honor LITELLM_UI_API_DOC_BASE_U..." | Re-trigger Greptile

import useProxySettings from "@/app/(dashboard)/hooks/proxySettings/useProxySettings";

export function resolveDocBaseUrl(docBaseUrl: string | null | undefined, fallback: string): string {
return docBaseUrl && docBaseUrl.trim() ? docBaseUrl : fallback;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Unnormalized documentation base URL

If LITELLM_UI_API_DOC_BASE_URL contains surrounding whitespace or a trailing slash, this returns the raw value and the changed consumers append paths directly, producing copied endpoints such as https://gateway.example.com/mcp or https://gateway.example.com//toolset/name/mcp that clients can reject or route incorrectly.

Suggested change
return docBaseUrl && docBaseUrl.trim() ? docBaseUrl : fallback;
return docBaseUrl?.trim().replace(/\/+$/, "") || fallback;

Knowledge Base Used: Admin dashboard (ui/litellm-dashboard)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MCP Servers documentation uses PROXY_BASE_URL instead of LITELLM_UI_API_DOC_BASE_URL

1 participant