Commit graph

61 commits

Author SHA1 Message Date
tin-berri
b417e858f9
fix(mcp): load MCP tool configuration tools via the OBO/passthrough-aware GET path (#29960)
* fix(ui): load MCP tool configuration tools via the OBO/passthrough-aware GET path

* fix(mcp): admin-only include_disabled_tools so the settings UI shows toggled-off tools

* fix(ui): repopulate MCP server edit form when server data loads after mount (OAuth return)

* fix(ui): persist MCP OAuth token on save and return to the Settings tab after authorize

* fix(ui): scope MCP OAuth callback to the initiating form so create and edit flows don't cross-talk

* fix(ui): derive OAuth-return Settings tab via lazy state init instead of setState-in-effect

* Fix MCP OAuth edit token handling

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
(cherry picked from commit 51ba6e39cd)
2026-06-15 18:21:29 -07:00
milan-berri
1f171ee018
fix(ui): require new expiration when regenerating an expired key (#29838) 2026-06-06 09:18:19 -07:00
ryan-crabbe-berri
7edf3a9cb5
style(ui): run prettier --write across the dashboard (#29622)
Formatting-only pass; no logic changes. Brings the UI into compliance
with .prettierrc so the new format-check CI job passes
2026-06-04 11:37:54 -07:00
yuneng-jiang
f0ebfb2a1b
fix(ui): break logout redirect loop across origins (#29360)
When the user has visited both the dev UI (e.g. localhost:3000) and the
proxy UI (e.g. localhost:4000) in the same tab, logging out from the dev
origin produced an infinite logout/login redirect.

The proxy-side LoginPage's "is the user still authenticated?" check
was reading getCookie("token"), which falls back to sessionStorage when
document.cookie has no token. The cross-origin clearTokenCookies() call
from the dev origin can clear cookies on the shared hostname, but cannot
reach sessionStorage on the proxy origin (sessionStorage is per-origin),
so the fallback returned a stale token and LoginPage interpreted the
user as logged in, redirecting back to the dev origin. Dev origin then
saw no cookie and redirected to LoginPage, repeating ~20x per second.

This change introduces getCookieFromDocument(), a cookie-only read with
no sessionStorage fallback, and uses it in LoginPage's already-logged-in
check. The HttpOnly-reverse-proxy defense from PR #23532 is unaffected:
storeLoginToken still writes both the JS cookie at /ui and the
sessionStorage backup, and getCookie still falls back for callers that
want the full read path.
2026-05-30 19:02:29 -07:00
Sameer Kankute
ef36e89638
feat(mcp): Add tool call and tool list support via UI for Oauth mcps (#28454)
* feat(mcp): cache OAuth token client-side so Tools tab loads without re-auth

After a user creates an OAuth MCP server and completes the authorization
flow, the resulting access token is now stored in sessionStorage keyed by
server_id.  The MCP Tools tab reads this cached token and includes it as
an MCP auth header when listing and invoking tools, so the user never sees
an empty tool list.  When the session ends (tab close / new browser) an
Authorize button re-triggers the flow without leaving the Tools screen.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* fix(ui/mcp): surface listMCPTools 401 errors so auth gate reappears

listMCPTools previously swallowed all errors (including HTTP 401) by
returning a synthetic { tools: [], error: 'network_error', ... } payload.
That made the useQuery retry-on-401 guard and mcpToolsError dead code,
so expired OAuth tokens never re-triggered the auth gate.

- Throw an enhanced Error with .status attached on non-2xx responses
  (still preserves the legacy shape for true network failures so the
  caller can render a generic message without crashing).
- Clear the cached OAuth session token when the tools query fails with
  401, mirroring callMCPTool's onError handler so the Authorize button
  is shown again.
- Surface mcpToolsError in the existing error banner.

Co-authored-by: Yassin Kortam <yassin@berri.ai>

* fix(mcp-tools): stable onSuccess + reuse parsed flow state

- Pass stable setOauthToken setter directly as onSuccess to avoid
  recreating useToolsOAuthFlow's resumeOAuthFlow on every render.
- Reuse the already-parsed FLOW_STATE_KEY value (peeked) instead of
  re-reading and re-parsing sessionStorage in resumeOAuthFlow.

Co-authored-by: Yassin Kortam <yassin@berri.ai>

* fix(ui/mcp): restore listMCPTools never-throws contract

The previous fix made listMCPTools throw on HTTP errors while still
returning a synthetic object on network errors. This inconsistent
contract broke existing callers (MCPToolPermissions, MCPAppsPanel,
MCPConnectPicker) which inspect result.error / result.message and
expect the function to never throw.

- Return a normalized { tools: [], error, message, status, ... }
  object on HTTP errors (instead of throwing) so all callers see a
  consistent shape and the user-visible error text from
  result.message is preserved.
- Convert the returned error object into a thrown Error inside the
  one caller that needs it — the useQuery in mcp_tools.tsx — so the
  401 retry/onError handlers still trigger and clear the cached
  OAuth token.

Co-authored-by: Yassin Kortam <yassin@berri.ai>

* fix greptile

* fix(mcp): align OAuth header alias lookup with dashboard sanitization

Backend auth header resolution now matches x-mcp-{alias} keys produced by
the dashboard sanitizer, and the Tools tab re-syncs OAuth tokens when
serverId changes.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(mcp): widen auth header lookup types for list_tools

Accept legacy str | dict server auth maps and annotate list_tools
server_auth_header as Union[str, dict] for mypy.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(ui): extract shared buildCallbackUrl/clearStorage for MCP OAuth hooks

Hoist the duplicate buildCallbackUrl and clearStorage helpers out of
useToolsOAuthFlow and useUserMcpOAuthFlow into a new shared module
src/hooks/mcpOAuthUtils.ts so the two hooks cannot drift if the URL
construction or storage cleanup logic needs to change.

Co-authored-by: Yassin Kortam <yassin@berri.ai>

* fix(ui): don't gate M2M OAuth MCP servers behind interactive authorize

M2M (client_credentials) OAuth servers share auth_type="oauth2" with
interactive PKCE servers, but the backend fetches their token internally
and they typically lack a user authorization endpoint. Gating tool
listing on them rendered an Authorize button that would fail or redirect
incorrectly. Detect M2M via the presence of token_url (matching the
existing heuristic in mcp_server_edit.tsx) and skip the auth gate.

Co-authored-by: Yassin Kortam <yassin@berri.ai>

* fix(ui/mcp): return error shape when listMCPTools JSON parse fails

Restore the never-throws contract when response.json() fails on a 2xx
body so callers do not receive null and crash on result.tools.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Yassin Kortam <yassin@berri.ai>
2026-05-22 09:04:04 -07:00
ishaan-berri
12e59c8798
Fix internal tag usage scoping (#27315)
* Scope internal tag usage to own keys

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Add internal tag usage unowned key regression test

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Handle empty internal tag usage scopes safely

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Add tag activity database guard

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: oss-agent-shin <279349115+oss-agent-shin@users.noreply.github.com>
Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>
2026-05-11 10:44:50 -07:00
Yuneng Jiang
b1ee9c4fc5
fix(rbac): restore admin-viewer read parity for Logs page + settings reads
Admin Viewer (proxy_admin_viewer) was being blocked from endpoints it should
be able to read. Most visibly the UI Logs page rendered empty because every
filter and detail call (/spend/logs/ui, /spend/logs/ui/{id},
/spend/logs/session/ui, /customer/list) was rejected at the route_checks
layer even though the underlying handlers permit admin-viewer.

Backend:
- Extend admin_viewer_routes to include spend_tracking_routes,
  /customer/{list,info}, /spend/logs/* detail routes, callback / config /
  budget / alerting reads, and model cost map status/source.
- Replace bare `user_role != PROXY_ADMIN` checks in read-only handlers
  (/budget/list, /budget/settings, /alerting/settings, /invitation/info,
  /config/field/info, /config/list, /schedule/model_cost_map_reload/status,
  /model/cost_map/source) with `_user_has_admin_view()`.

UI:
- Add `rolesAllowedToViewWriteScopedPages` (rolesWithWriteAccess + Admin
  Viewer) and use it for the "Models + Endpoints" and "Agents" sidebar
  items so admin viewers see them read-only. Playground stays gated by
  rolesWithWriteAccess (cost-incurring).
- Hide Add / Edit / Delete buttons in the LLM Credentials panel for
  non-proxy-admin viewers.

Tests:
- 31 parametrized route_checks cases for the Logs + settings endpoints,
  with internal-user negative coverage to ensure the gate isn't widened.
- 9 handler-level integration tests (FastAPI TestClient) verifying
  admin viewer is no longer blocked at the handler layer.
- New leftnav cases asserting Playground hidden / Models + Agents / Logs
  visible to Admin Viewer.
- New roles + credentials test cases for the UI write-gate.
2026-04-29 19:21:41 -07:00
Ryan Crabbe
1f6e01802d
Show absolute date in Budget Reset column
Relative labels ("today", "in 2 days", "on May 12, 2026") mixed three
shapes in one column, breaking scannability. Always render MMM D, YYYY
for consistency and easier at-a-glance comparison across members.
2026-04-23 15:57:22 -07:00
Ryan Crabbe
5e5a94ac8d
Surface budget_reset_at on team info and members tab
Adds a formatBudgetReset helper (dayjs-based, with validity guard) that
renders the next reset as "today" / "in N days" / "on MMM D, YYYY". The
team budget card now shows the team's reset timestamp and the member-
default reset (when a shared team_member_budget is configured), and the
Members tab gains a Budget Reset column per member.
2026-04-22 17:28:05 -07:00
Ryan Crabbe
5aba1841cc
Extract shared PKCE helpers into src/utils/pkce.ts
Deduplicates base64UrlEncode, generateCodeVerifier, and
generateCodeChallenge which were copy-pasted across useMcpOAuthFlow
and useUserMcpOAuthFlow hooks.
2026-04-16 10:35:52 -07:00
Sameer Kankute
972e42c7fd
Merge branch 'main' into litellm_oss_staging_04_04_2026 2026-04-14 20:23:06 +05:30
Yuneng Jiang
20ed120d1a
[Fix] Let setSecureItem propagate storage errors to callers
Remove the silent try/catch from setSecureItem so OAuth hooks can
surface actionable "enable storage" guidance instead of a cryptic
"state lost" error after the round-trip. Add a local try/catch in
ChatUI where the storage write is non-critical.
2026-04-08 22:13:55 -07:00
Yuneng Jiang
70a5c27cbd
[Fix] Address review feedback on storage utility and Dockerfiles
- Dockerfile.health_check: HEALTHCHECK now verifies the script is intact
  instead of unconditionally exiting 0
- secureStorage.ts: replace deprecated escape/unescape with
  encodeURIComponent/decodeURIComponent; don't delete legacy values on
  decode failure so in-flight flows can time out naturally
- OAuth callback: add same-origin check before redirecting to stored
  return URL
2026-04-08 17:51:34 -07:00
Yuneng Jiang
a881ac5133
[Fix] UI: resolve CodeQL security alerts and Dockerfile.health_check hardening
Port security fixes from litellm_v1.82.3.dev.6:
- Use secureStorage (sessionStorage wrapper) instead of raw storage for tokens
- Add URL validation for stored worker URLs to prevent open redirects
- Add same-origin checks before redirecting to stored return URLs
- Harden Dockerfile.health_check with non-root user and exec-form HEALTHCHECK
2026-04-08 17:21:25 -07:00
Hendrik Jaks
f233520c44
fix(ui): resolve login redirect loop when reverse proxy adds HttpOnly to cookies (#23532)
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
* fix(ui): resolve login redirect loop when reverse proxy adds HttpOnly to cookies

When LiteLLM is behind nginx-ingress or similar with security-hardened
configs, the reverse proxy adds HttpOnly to all Set-Cookie headers. This
makes the JWT token unreadable by JavaScript, causing an infinite login
redirect loop. Fix by returning the JWT token in the /v2/login response
body so the frontend can set a JS-accessible cookie directly.

Fixes #19663

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Greptile review feedback

- Add window guard to setTokenCookie for SSR consistency with clearTokenCookies
- Add SSR test for window undefined case
- Add code comment explaining why JWT is included in response body

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address second round of Greptile review feedback

- Add loginCall integration tests verifying setTokenCookie is called with
  token and skipped when absent (backward-compatibility path)
- Use encodeURIComponent/decodeURIComponent in setTokenCookie/getCookie
  for defense-in-depth against non-standard token formats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update ui/litellm-dashboard/src/utils/cookieUtils.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Update ui/litellm-dashboard/src/utils/cookieUtils.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(ui): use sessionStorage instead of cookie for login token storage

Replace setTokenCookie (which is a no-op when reverse proxy adds HttpOnly)
with storeLoginToken using sessionStorage. Add sessionStorage fallback to
getCookie so the token is found even when the cookie is HttpOnly. Also handle
'=' in cookie values with .slice(1).join("=") and clear sessionStorage on
logout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ui): use shared getCookie in page.tsx and user_dashboard.tsx

Replace local getCookie functions in page.tsx and user_dashboard.tsx
with the shared one from cookieUtils that has the sessionStorage
fallback. Without this, the HttpOnly cookie fix was incomplete —
page.tsx (the dashboard entry point) could not read the token,
causing the redirect loop to persist.

Also scope the sessionStorage fallback to the "token" key only,
and clear sessionStorage in page.tsx deleteCookie.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ui): scope deleteCookie sessionStorage cleanup to token key only

Also document the sessionStorage cross-tab trade-off: per-tab scope
means users behind an HttpOnly proxy must log in once per tab, but
this is intentional to avoid localStorage XSS exposure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update ui/litellm-dashboard/src/utils/cookieUtils.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* style: remove stray double blank line in user_dashboard.tsx

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ui): guard storeLoginToken against empty/whitespace-only tokens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ui): preserve sessionStorage token across beforeunload clear

The existing beforeunload handler calls sessionStorage.clear() to
flush cached UI data on page refresh. This also wiped the token
stored by storeLoginToken, re-introducing the redirect loop after
any page refresh in the HttpOnly proxy scenario. Now the token is
saved and restored across the clear.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(ui): set JS-accessible cookie at /ui path as HttpOnly workaround

sessionStorage alone is unreliable. Also set the token via
document.cookie at path=/ui — nginx only adds HttpOnly to server-set
Set-Cookie headers, so a JS-set cookie is always readable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ui): use dynamic cookie path based on server_root_path

Hardcoded path=/ui breaks when LiteLLM is deployed with a custom
server_root_path. Now derives the cookie path from serverRootPath
so it works at /ui, /myapp/ui, etc.

Also reuse clearTokenCookies() in deleteCookie() to avoid duplication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(ui): remove circular dependency in cookieUtils.ts

Derive the UI cookie path from window.location.pathname instead of
importing serverRootPath from networking.tsx. This breaks the
cookieUtils → networking → cookieUtils cycle that could cause
serverRootPath to be undefined under certain bundler configurations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ui): harden getUiCookiePath regex and add missing tests

- Use regex /\/ui(?=\/|$)/ to match "/ui" only as a full path segment,
  preventing false matches on paths like "/my-ui-tool/login".
- Add unit tests for storeLoginToken empty/whitespace guard and
  cookie-at-/ui-path behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: fix Black formatting in audit_logs.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix CI: formatting, test params, remove token from login JSON

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: reformat with Black 23.x to match CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: keep token in login JSON body for UI storeLoginToken flow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use storeLoginToken in exchangeLoginCode, add credentials include

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* revert: remove unrelated changes from HttpOnly cookie fix branch

Reset files not related to the login cookie fix back to main:
- prometheus.py, bedrock converse, guardrail handler
- auth_checks.py, reset_budget_job.py, audit_logs.py
- test_user_api_key_auth.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert "revert: remove unrelated changes from HttpOnly cookie fix branch"

This reverts commit 0684a1e275.

* Revert "fix: use storeLoginToken in exchangeLoginCode, add credentials include"

This reverts commit 866405f443.

* Revert "fix: keep token in login JSON body for UI storeLoginToken flow"

This reverts commit 086c41640c.

* Revert "fix: reformat with Black 23.x to match CI"

This reverts commit b2c3334c88.

* Revert "fix CI: formatting, test params, remove token from login JSON"

This reverts commit 2905d47bd4.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-04-06 11:13:06 -07:00
yuneng-jiang
5d33cc66a0 Add unit tests for 5 previously untested UI dashboard files
Tests added for: UiLoadingSpinner, HashicorpVaultEmptyPlaceholder,
PageVisibilitySettings, errorUtils, and mcpToolCrudClassification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 12:53:20 -07:00
Ishaan Jaff
b0aa71ed9b
feat(ui): group MCP tools by CRUD risk category in allowlist panels (#23403)
* feat(ui): group MCP tools by CRUD risk category in tool permission panels

Adds a CRUD-classification layer to the MCP tool allowlist UI so admins
can allow/block an entire risk category (Read / Create / Update / Delete)
with a single toggle instead of managing a flat list of individual tools.

- New `mcpToolCrudClassification.ts` utility: regex-based classifier that
  buckets tool names/descriptions into read/create/update/delete/unknown
- New `McpCrudPermissionPanel` component: collapsible sections per CRUD
  group, group-level Switch toggle, individual tool checkboxes, risk badges
  (green Safe / yellow Medium / red High Risk)
- `mcp_tool_configuration.tsx`: adds "Risk Groups / Flat List" radio toggle;
  defaults to the CRUD-grouped view, flat list is still accessible
- `MCPToolPermissions.tsx` (key/team assignment): replaces flat checkboxes
  with the CRUD panel; adds per-server view toggle; delete tools are blocked
  by default for newly-added servers (safer default for key/team scoping)

No backend or schema changes — uses existing `allowed_tools` and
`mcp_tool_permissions` fields.

* fix(mcp): OAuth2 chat connect - tools fetch, auth flow, and status fixes

- schema.prisma: add missing MCP table fields (approval_status, submitted_by, submitted_at, reviewed_at, review_notes) to prevent destructive migrations
- rest_endpoints.py: inject user OAuth token via extra_headers for OAuth2 servers so tools list is populated; add server name->UUID resolution so MCPConnectPicker name lookups work
- mcp_registry.json: fix Atlassian defaults (transport: http, url: .../v1/mcp)
- ChatPage.tsx: read mcpOauthReturn param to init sidebarView="apps" on OAuth return, clean up param after mount
- MCPAppsPanel.tsx: auto-add OAuth2 servers to selectedServers when credential detected; onConnect also enables server for chat; disconnect removes from selectedServers
- mcp_servers.tsx: sort servers by created_at DESC
- useUserMcpOAuthFlow.tsx: append mcpOauthReturn=apps to return URL so Apps panel is mounted on return

* fix(mcp-crud-ui): address greptile review feedback

- use Checkbox (not Switch) for group toggle so indeterminate works
- add toolPermissionsRef to avoid stale closure race on concurrent server fetches
- remove unused blockDeleteByDefault prop from McpCrudPermissionPanel
- classify tools by name first; fall back to description only when name yields no match
- add Risk Groups / Flat List toggle to mcp_tool_configuration.tsx

* fix(mcp-crud-ui): address greptile 3/5 review

- remove non-functional XIcon remove-server button (no onRemoveServer prop wired)
- fix stale closure in MCPAppsPanel auto-enable effect: use serversRef/selectedServersRef
- remove utility re-export from McpCrudPermissionPanel (classifyToolOp, groupToolsByCrud)
- remove redundant selectedTools.length === 0 guard (always true when !toolPermissions[id])

* fix(mcp-crud-ui): address greptile 3/5 review round 2

- check READ_RE before DELETE_RE in classifyToolOp so tools like
  get_removed_entries are not silently blocked by delete-by-default
- expand undefined (allow-all) to full tool name list instead of
  collapsing to [] (allow-none) in MCPToolPermissions and mcp_tool_configuration
- log OAuth credential fetch failures instead of silently swallowing them

* fix: cursor-pointer on read-only rows, stable sort, simplify handleCrudPanelChange

* fix: sanitize user_id/server_id in log to prevent log injection

* fix: add OAuth headers to call_tool_rest_api, fix stale accessToken closure, fix group toggle on filtered subset

* fix: batch OAuth creds query, hide empty CRUD groups on search, onChange stability

* fix: double-add race, conditional bulk query, narrow DELETE_RE, hoist search input

* fix(mcp): clear oauthConnected on deselect; null guard on allowedTools prop

* fix(mcp): remove user-provided values from debug log to fix log-injection lint

* fix(mcp): fix allowedTools undefined semantics; remove unused import and color field
2026-03-11 21:15:25 -07:00
Ishaan Jaff
f5e5d17e4a
fix(mcp): fix OpenAPI OAuth flow — transport mapping, error messages, and discovery bypass (#23315)
* fix(mcp): fix OpenAPI OAuth flow — transport mapping, error messages, and discovery bypass

Three bugs fixed to make the end-to-end OAuth flow work for OpenAPI MCP servers:

1. **Transport mapping in getTemporaryPayload**: `TRANSPORT.OPENAPI` is a UI-only concept;
   the backend only accepts `"http"`, `"sse"`, or `"stdio"`. The pre-OAuth temp-session
   call was sending `transport: "openapi"` and getting a 422. Fixed by mapping to `"http"`.

2. **deriveErrorMessage handles FastAPI 422 arrays**: FastAPI validation errors return
   `detail` as an array of `{loc, msg, type}` objects. The shared error extractor was
   returning the array directly, causing `Error: [object Object]`. Fixed to map each
   item to its `.msg` field.

3. **Skip OAuth discovery when authorization_url already provided**: `build_mcp_server_from_table`
   was unconditionally calling `_descovery_metadata(server_url)` for OAuth servers. For
   OpenAPI servers the url is the spec JSON file, not the API base — this caused a timeout
   fetching e.g. the GitHub spec (2 MB). Fixed by skipping discovery when `authorization_url`
   is already set.

Also: collapsible auth section in MCP server form, "Create OAuth App →" link next to
Client ID when a docs URL is available (e.g. GitHub OAuth App creation page), and
`extractErrorMessage` helper in `useMcpOAuthFlow` for cleaner error display.

* refactor(mcp): extract needs_discovery flag and reduceStaticHeaders helper

* feat(mcp): user OAuth connect flow — OAuthConnectModal, MCPCredentialsTab, useUserMcpOAuthFlow

Adds the user-facing MCP OAuth2 PKCE connect flow:

- OAuthConnectModal: modal that launches the PKCE flow for a user to connect to an MCP server
- MCPCredentialsTab: credentials management tab in the MCP apps panel
- useUserMcpOAuthFlow: hook that handles the full PKCE auth code exchange for user-level connections
- MCPAppsPanel: wires up the new credentials tab and connect modal
- ChatPage: further cleanup after responses-API revert
- db.py / mcp_management_endpoints.py / _types.py: backend support for storing user MCP credentials

* fix(mcp): make client_id optional in /authorize — use server's stored client_id when not provided

* address greptile review feedback

* fix(mcp): narrow bare except to RecordNotFoundError in BYOK credential delete

* refactor(mcp): move inline imports to module level in db.py

* docs(claude): add MCP OAuth, transport mapping, and browser storage patterns

* fix(security): remove accessToken from sessionStorage in OAuth flow state

The LiteLLM API key was being serialised into sessionStorage as part of
StoredFlowState. After the OAuth redirect the component re-mounts with the
same accessToken prop, so it never needed to be stored. Read it from props
in resumeOAuthFlow instead.

* fix(ui): remove duplicate extractErrorMessage, sessionStorage-only in admin OAuth hook, call delete API on disconnect

* fix(ui): guard resumeOAuthFlow against wrong hook instance consuming OAuth result

* fix(ui): separate OAuth result keys per flow, sessionStorage-only, surface revoke errors

* fix(ui): remove dead OAuthConnectModal, revert tsconfig jsx mode to preserve

* fix(mcp): guard BYOK overwrite in oauth credential store, raise clear error when client_id absent

* fix: forward OAuth error params in callback, fix BYOK guard exception handling in db.py
2026-03-11 16:16:08 -07:00
Dibyo Mukherjee
518cd3ef60 feat(ui): add key creation deep-links with SSO return URL support
Enables deep-linking directly to the key creation modal with prefilled
form data via URL parameters, including support for preserving these
deep-links through SSO authentication flows.

Key Creation Deep-links:
- Auto-open key creation modal via ?create=true parameter
- Prefill form fields from URL parameters (team_id, key_alias, models, etc.)
- Role-based access control for auto-open (requires write access)
- Race condition protection for redirect handling

Example: /ui?create=true&team_id=abc&key_alias=my-key&models=gpt-4,claude-3

SSO Return URL Preservation:
- Cookie-based return URL storage (works across ports for SSO flows)
- URL validation to prevent open redirect attacks
- Support for both dev and production environments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-26 15:41:54 -05:00
yuneng-jiang
c47866afb9 useAuthorized refactor 2026-02-04 16:37:45 -08:00
yuneng-jiang
c86f310ac5 Allow prevent team admins from deleting users from teams 2026-01-14 22:15:48 -08:00
yuneng-jiang
60c39255d5 Adding unit testing coverage 2026-01-03 17:25:46 -08:00
yuneng-jiang
a17980c744 feat: hide new badges 2025-12-31 10:42:34 -08:00
yuneng-jiang
40549bc361 Deprecate useTeam in favor of react query 2025-12-23 20:15:42 -08:00
yuneng-jiang
87e915e4e2 Resolve team alias in usage page 2025-12-19 16:43:52 -08:00
yuneng-jiang
0487c610b8 Add Model Tab Visibility Changes 2025-12-16 11:25:43 -08:00
yuneng-jiang
5b0bf86ee5 Usage Entity labels 2025-12-12 12:13:51 -08:00
yuneng-jiang
4e4a2e7ca2 Spend logs spend column enhancement 2025-12-06 16:14:33 -08:00
yuneng-jiang
b14b4a7112 New login screen using v2/login 2025-12-03 15:05:29 -08:00
yuneng-jiang
adfdcf1d61
[Fix] UI - Hide Default Team Settings From Proxy Admin Viewers (#16900)
* Add fallback in sort to prevent NoneType and str comparison

* Hide Default Team Settings from Proxy Admin Viewers

---------

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2025-11-23 22:01:38 -08:00
yuneng-jiang
b9759b4bfa
[Feature] UI - Add LiteLLM Params to Edit Model (#16496)
* Add LiteLLM Params to Edit Model

* Fixed tests
2025-11-11 18:52:11 -08:00
yuneng-jiang
39ae7549a4
[Feature] UI - Model Info Page Health Check (#16416)
* Add test connection button to model info page

* Unused import
2025-11-10 11:10:06 -08:00
yuneng-jiang
11af05f5f4
Small issues (#16406) 2025-11-08 16:05:42 -08:00
Krish Dholakia
e0c4baf66f
fix(ui/): fix routing for custom server root path (#15701)
* fix(ui/): fix routing for custom server root path

* fix: fix eslint errors
2025-10-23 13:59:29 -07:00
yuneng-jiang
4d070abbce Key Max Budget Removal Error Fix 2025-10-17 12:04:58 -07:00
Krish Dholakia
c8b93c3940
Merge pull request #15389 from BerriAI/litellm_usage_spend_per_day_chart_fix
fix: usage page >> Model Activity >> spend per day graph: y-axis clipping on large spend values
2025-10-10 13:08:26 -07:00
Achintya Rajan
73eafed51c removed unused imports 2025-10-10 10:25:00 -07:00
Achintya Rajan
5fca481ebb removing unused imports 2025-10-10 10:24:57 -07:00
Achintya Rajan
310b2da33e abbreviates large spend values, increases y-axis width 2025-10-09 14:54:21 -07:00
Achintya Rajan
00f61b214c more window guards 2025-10-06 14:17:02 -07:00
Achintya Rajan
cee408c0c0 diagnosing next build issue 2025-10-06 14:03:53 -07:00
Achintya Rajan
03804cb1d2 preliminary virtual-keys refactor
simplifies handleCreate function for CreateKeyModal

moved hooks, components, files where I want them

moved virtual-key page to (console) for common layout

added layout for refactored console file structure, sidebar

wired teams to refactored components

fixing type issue

wired new top level hook useAuthorized

Adds routing to unrefactored pages

Update leftnav.tsx

Update useAuthorized.ts

useAuthorized in virtual-keys/page and deprecation notices

prelim VirtualKeyViewPage, removed old comment

Delete page.tsx
2025-10-06 10:43:26 -07:00
=
5197268a58 added and ran prettier autoformatter 2025-10-04 18:19:48 -07:00
Krrish Dholakia
fff40e2ed6 fix(datautils.ts): fix clipboard copy issue on http endpoints 2025-10-04 11:29:15 -07:00
Jack Venberg
560e96570e Fix: Session Token Cookie Infinite Logout Loop 2025-10-02 15:02:07 -07:00
tanjiro
f7a3af5cde
new notifications (#13813) 2025-08-20 14:32:04 -07:00
tanjiro
be109c2180 put the error toast on the ui 2025-08-13 23:05:11 +09:00
Krish Dholakia
94aa6b0b5d
Bulk User Edit - additional improvements - edit all users + set 'no-default-models' on all users (#12925)
* feat(bulk_user_update/): support updating all users on proxy

* fix(bulk_edit_user.tsx): persist user settings when 'add to team' clicked

* fix(team_endpoints.py): bulk add all proxy users to team

supports flow from UI to add all existing users to a team

* fix: minor fixes

* feat(user_edit_view.tsx): support setting no default model on user edit

allows preventing users from calling models outside team scope

* fix(user_edit_view.tsx): prevent triggering submit when 'cancel' is clicked

* refactor(internal_user_endpoints.py): refactor to reduce function size
2025-07-27 10:12:30 -07:00
tanjiro
720b94fd2b
Add Copy-on-Click for IDs (#12615)
* added the mcp_connect copy button to key_info_view

* user id copy button

* copy button on session view

* model id copy

* more copy buttons

* icon size
2025-07-15 11:25:57 -07:00
tanjiro
8bf94b9090
Comma separated spend and budget (#12317)
* all_keys_table, key_info_view, organizations

* teams

* the whole usage page

* teams page

* users table

* user info

* more commas

* some more commas
2025-07-04 11:14:39 -07:00