mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-02 12:21:10 +00:00
* 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
113 lines
3.3 KiB
JSON
113 lines
3.3 KiB
JSON
{
|
|
"name": "litellm-dashboard",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "next dev",
|
|
"dev:webpack": "next dev --webpack",
|
|
"build": "next build",
|
|
"start": "next start",
|
|
"lint": "next lint",
|
|
"test": "vitest",
|
|
"test:dot": "vitest --reporter=dot",
|
|
"test:watch": "vitest -w",
|
|
"test:coverage": "vitest run --coverage",
|
|
"format": "prettier --write .",
|
|
"format:check": "prettier --check .",
|
|
"e2e": "playwright test --config e2e_tests/playwright.config.ts",
|
|
"e2e:ui": "playwright test --ui --config e2e_tests/playwright.config.ts",
|
|
"knip": "knip",
|
|
"knip:fix": "knip --fix"
|
|
},
|
|
"dependencies": {
|
|
"@anthropic-ai/sdk": "^0.54.0",
|
|
"@headlessui/tailwindcss": "^0.2.0",
|
|
"@heroicons/react": "^1.0.6",
|
|
"@remixicon/react": "^4.1.1",
|
|
"@tanstack/react-pacer": "^0.2.0",
|
|
"@tanstack/react-query": "^5.64.1",
|
|
"@tanstack/react-table": "^8.20.6",
|
|
"@tremor/react": "^3.13.3",
|
|
"@types/papaparse": "^5.3.15",
|
|
"antd": "^5.13.2",
|
|
"cva": "^1.0.0-beta.3",
|
|
"dayjs": "^1.11.19",
|
|
"jwt-decode": "^4.0.0",
|
|
"lucide-react": "^0.513.0",
|
|
"moment": "^2.30.1",
|
|
"next": "^16.1.6",
|
|
"openai": "^4.93.0",
|
|
"papaparse": "^5.5.2",
|
|
"react": "^18.3.1",
|
|
"react-copy-to-clipboard": "^5.1.0",
|
|
"react-dom": "^18.3.1",
|
|
"react-json-view-lite": "^2.5.0",
|
|
"react-markdown": "^9.0.1",
|
|
"react-syntax-highlighter": "^15.6.6",
|
|
"remark-gfm": "^4.0.1",
|
|
"tailwind-merge": "^3.2.0",
|
|
"uuid": "^11.1.0"
|
|
},
|
|
"devDependencies": {
|
|
"@neondatabase/api-client": "^2.6.0",
|
|
"@playwright/test": "^1.57.0",
|
|
"@tailwindcss/forms": "^0.5.7",
|
|
"@testing-library/dom": "^10.4.1",
|
|
"@testing-library/jest-dom": "^6.8.0",
|
|
"@testing-library/react": "^16.3.0",
|
|
"@testing-library/user-event": "^14.6.1",
|
|
"@types/babel__traverse": "^7.28.0",
|
|
"@types/lodash": "^4.17.15",
|
|
"@types/node": "20.19.37",
|
|
"@types/react": "18.2.48",
|
|
"@types/react-copy-to-clipboard": "^5.0.7",
|
|
"@types/react-dom": "^18",
|
|
"@types/react-syntax-highlighter": "^15.5.11",
|
|
"@types/uuid": "^10.0.0",
|
|
"@vitest/coverage-v8": "^3.2.4",
|
|
"@vitest/ui": "^3.2.4",
|
|
"autoprefixer": "^10.4.17",
|
|
"dotenv": "^17.2.3",
|
|
"eslint": "^9.39.2",
|
|
"eslint-config-next": "15.5.10",
|
|
"eslint-config-prettier": "^10.1.8",
|
|
"eslint-plugin-unused-imports": "^4.2.0",
|
|
"jsdom": "^27.0.0",
|
|
"knip": "^5.83.1",
|
|
"postcss": "^8.4.33",
|
|
"prettier": "3.2.5",
|
|
"tailwindcss": "^3.4.1",
|
|
"typescript": "5.9.3",
|
|
"vite": "^7.1.11",
|
|
"vitest": "^3.2.4"
|
|
},
|
|
"overrides": {
|
|
"diff": ">=8.0.3",
|
|
"prismjs": ">=1.30.0",
|
|
"webpack-dev-server": ">=5.2.1",
|
|
"mermaid": ">=11.10.0",
|
|
"js-yaml": ">=4.1.1",
|
|
"glob": ">=11.1.0",
|
|
"tar": ">=7.5.10",
|
|
"minimatch": ">=10.2.4",
|
|
"@isaacs/brace-expansion": ">=5.0.1",
|
|
"node-forge": ">=1.3.2",
|
|
"lodash-es": ">=4.17.23",
|
|
"lodash": ">=4.17.23",
|
|
"@babel/traverse": ">=7.23.2",
|
|
"ws": ">=7.5.10",
|
|
"http-proxy-middleware": ">=2.0.9",
|
|
"tar-fs": ">=2.1.4",
|
|
"webpack-dev-middleware": ">=5.3.4",
|
|
"braces": ">=3.0.3",
|
|
"axios": ">=0.30.2",
|
|
"webpack": ">=5.94.0",
|
|
"serve-static": ">=1.16.0",
|
|
"path-to-regexp": ">=0.1.12"
|
|
},
|
|
"engines": {
|
|
"node": ">=18.17.0",
|
|
"npm": ">=8.3.0"
|
|
}
|
|
}
|