litellm/litellm/proxy
Ishaan Jaff 1bb713bc7b
feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850)
* feat(mcp): BYOK (Bring Your Own Key) for OpenAPI MCP servers with OAuth 2.1 flow

Adds per-user credential storage for BYOK MCP servers so external clients
can authenticate via standard OAuth 2.1 PKCE without needing a full identity
provider.

Backend:
- New DB table LiteLLM_MCPUserCredentials (user_id, server_id, credential_b64)
- is_byok, byok_description, byok_api_key_help_url fields on MCPServerTable
- OAuth 2.1 authorization server endpoints (/.well-known/oauth-authorization-server,
  /.well-known/oauth-protected-resource, /v1/mcp/oauth/authorize, /v1/mcp/oauth/token)
- 401 challenge with WWW-Authenticate header when BYOK server has no credential
- CRUD endpoints: POST/DELETE /v1/mcp/server/{id}/user-credential
- has_user_credential annotated on GET /v1/mcp/server response

UI:
- ByokCredentialModal: 2-step Connect flow (access description + API key entry)
- BYOK toggle + description fields on admin MCP server create form
- Connect/Connected state in MCP server table
- BYOK Demo page (/tools/byok-demo) showing full OAuth 2.1 PKCE flow

* feat(mcp/byok): redesign OAuth authorize page to match 2-step Connect mockup

- Step 1: L→S logos, requested access checklist, How it works box, Continue button
- Step 2: API key input, Save toggle, Duration pills (1h/24h/7d/30d/until_revoked), security note
- Matches screenshots: white modal on dark bg, progress dots, dark CTA buttons
- Authorize handler now fetches byok_description and byok_api_key_help_url from server registry
- CLAUDE.md: replace SQL snippet with proper DB migration troubleshooting guidance

* fix: address greptile review feedback (greploop iteration 1)

- XSS: escape all user-supplied values in _build_authorize_html() with html.escape()
- Open redirect: validate redirect_uri scheme and URL-encode code/state in redirect
- N+1 query: batch BYOK credential lookup into single find_many() call
- Critical path DB: add 60s TTL in-memory cache to _check_byok_credential()
- Encrypt BYOK credentials at rest using encrypt_value_helper/decrypt_value_helper

* fix(byok): update OAuth popup with LiteLLM logo, MCP title suffix, remove emojis

* fix(byok-demo): fix token endpoint URL (/v1/mcp/oauth/token not /v1/mcp/token)

* feat(byok): inject stored BYOK credential as mcp_auth_header on tool execution

* feat(byok): use contextvars to inject per-user credential into OpenAPI tool closures; remove byok-demo from LiteLLM UI

OpenAPI tools have auth headers baked into their closures at registration time. BYOK servers have
no static auth token, so per-user credentials were never reaching the HTTP calls.

Fix: add _request_auth_header ContextVar in openapi_to_mcp_generator.py. create_tool_function now
reads this var at call time and overrides the Authorization header if set. execute_mcp_tool resolves
the MCP server and performs BYOK checks before the local-tool dispatch branch, then sets the
ContextVar around _handle_local_mcp_tool so the credential flows into the HTTP request.

Also remove the /tools/byok-demo page from the LiteLLM UI dashboard — the demo lives at
~/Downloads/litellm-byok-demo/index.html (served separately on port 8080).

* fix: address greptile review feedback (greploop iteration 2)

- Cache invalidation: add _invalidate_byok_cred_cache() and call it after
  store_user_credential() in both token endpoint and management endpoint
- Unbounded cache: add _BYOK_CRED_CACHE_MAX_SIZE=4096 with clear-on-overflow
- Unbounded auth codes: add _AUTH_CODES_MAX_SIZE=1000 with 503 on overflow
- Double DB query: merge _check_byok_credential + _get_byok_credential into
  single _get_byok_credential call; raise 401 inline if None returned
- Sidebar: remove byok-demo entry (page was deleted in prior commit)
- JWT comment: document why byok_session HS256 token can't be used as proxy auth

* fix: address greptile review feedback (greploop iteration 3)

- auth_type: pre-format Authorization header (Bearer/ApiKey/Basic) in server.py
  before setting ContextVar so openapi_to_mcp_generator respects server auth_type
- cache invalidation on delete: call _invalidate_byok_cred_cache after
  delete_user_credential so stale True entries don't persist for 60s
- ContextVar guard: only set _request_auth_header when mcp_auth_header is set,
  avoiding unnecessary ContextVar overhead on non-BYOK tool calls

* fix: address greptile review feedback (greploop iteration 4)

- Unified credential cache: store actual credential value (Optional[str])
  instead of just bool so _get_byok_credential also benefits from caching —
  eliminates the DB hit on every BYOK tool call within the 60s TTL window
- Extracted _write_byok_cred_cache() helper for consistent cache writes
- Replaced has_user_credential with get_user_credential in _check_byok_credential
  so one DB call satisfies both existence check and value retrieval
- Remove false 'encrypted at rest' claim from OAuth HTML and ByokCredentialModal

* Update tests/test_litellm/proxy/_experimental/mcp_server/test_byok_oauth_endpoints.py

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

* Update tests/test_litellm/proxy/_experimental/mcp_server/test_byok_oauth_endpoints.py

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

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-04 21:19:25 -08:00
..
_experimental feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850) 2026-03-04 21:19:25 -08:00
agent_endpoints Agent Tracing - support context_id based trace id propogation + nested llm calls (#22626) 2026-03-03 18:19:12 -08:00
analytics_endpoints fix(sql): Optimize SpendLogs queries to use timestamp filtering for index usage (#17504) 2025-12-04 21:52:57 -08:00
anthropic_endpoints fix(count_tokens): include system and tools in token counting API requests 2026-02-27 15:39:35 -03:00
auth Merge pull request #22372 from BerriAI/litellm_jwt_vkey_map 2026-03-05 06:24:49 +05:30
batches_endpoints Merge pull request #22728 from BerriAI/litellm_batch_expiry_validation_followup 2026-03-04 10:16:02 -08:00
client fix: prompt registry 2026-02-18 00:34:54 +05:30
common_utils Merge pull request #22103 from Harshit28j/litellm_feat_datadog_metrics 2026-02-28 17:25:23 +05:30
config_management_endpoints
container_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
credential_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
custom_hooks perf: use cached _safe_get_request_headers instead of dict(request.headers) 2026-02-17 16:11:50 -08:00
db [Feat] Add Tool Policies for AI Gateway (#22732) 2026-03-03 20:22:20 -08:00
discovery_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
example_config_yaml fix: prompt registry 2026-02-18 00:34:54 +05:30
fine_tuning_endpoints fix: Get custom_llm_provider from query param (#16731) 2025-11-17 19:56:41 -08:00
google_endpoints fix: Metadata / Trace ID Missing in S3 Streaming Callbacks 2026-02-25 14:16:21 +05:30
guardrails azure content enhancement... (#22581) 2026-03-04 10:22:30 -08:00
health_check_utils feat(proxy): limit concurrent health checks with health_check_concurrency (#20584) 2026-02-24 08:16:59 -08:00
health_endpoints fix(mypy): fix 3 mypy errors in presidio.py and _health_endpoints.py (#22422) 2026-02-28 10:46:27 -08:00
hooks Fix: Removed the process-level _encrypted_response_id_cache from __init__ 2026-03-04 12:30:49 +05:30
image_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
management_endpoints feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850) 2026-03-04 21:19:25 -08:00
management_helpers
middleware Fix inflight mypy 2026-03-02 19:41:32 +05:30
ocr_endpoints Enable local file support for OCR (#22133) 2026-02-27 10:50:02 -08:00
openai_evals_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
openai_files_endpoints Merge pull request #22728 from BerriAI/litellm_batch_expiry_validation_followup 2026-03-04 10:16:02 -08:00
pass_through_endpoints fix: catch exceptions in pass-through streaming logging handler (#21636) 2026-03-02 19:21:10 +05:30
policy_engine Guardrail Policy Versioning (#21862) 2026-02-21 20:14:31 -08:00
prompts fix: prompt registry 2026-02-18 00:34:54 +05:30
public_endpoints Development environment setup (#22432) 2026-02-28 14:50:06 -08:00
rag_endpoints tests and route permissions (#21508) 2026-02-18 16:58:38 -08:00
rerank_endpoints
response_api_endpoints feat(proxy): add WebSocket endpoint for responses API and route_llm_request support 2026-03-02 17:22:44 +05:30
response_polling fix: prompt registry 2026-02-18 00:34:54 +05:30
search_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
spend_tracking Agent Tracing - support context_id based trace id propogation + nested llm calls (#22626) 2026-03-03 18:19:12 -08:00
swagger Change favicon (#16837) 2025-11-19 20:38:22 -08:00
test_prompts
types_utils
ui_crud_endpoints [Feature] UI - Admin Settings: Add opt-in flag for Projects feature 2026-02-28 10:32:02 -08:00
vector_store_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
vector_store_files_endpoints fix: prompt registry 2026-02-18 00:34:54 +05:30
vertex_ai_endpoints fix: add .copy() to create_request_copy and tests for header caching 2026-02-18 09:44:35 -08:00
video_endpoints Revert "Litellm staging 01 15 2026" 2026-01-17 06:31:34 +09:00
.gitignore
__init__.py
_logging.py
_new_new_secret_config.yaml
_new_secret_config.yaml [Feat] Add Tool Policies for AI Gateway (#22732) 2026-03-03 20:22:20 -08:00
_super_secret_config.yaml fix: prompt registry 2026-02-18 00:34:54 +05:30
_types.py feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850) 2026-03-04 21:19:25 -08:00
cached_logo.jpg fix: prompt registry 2026-02-18 00:34:54 +05:30
caching_routes.py
common_request_processing.py Merge pull request #22559 from BerriAI/litellm_responses_websocket 2026-03-04 17:57:34 +05:30
compliance_checks.py Add compliance checker endpoints + UI panel (#21432) 2026-02-17 18:22:26 -08:00
custom_auth_auto.py
custom_prompt_management.py fix: prompt registry 2026-02-18 00:34:54 +05:30
custom_sso.py fix: prompt registry 2026-02-18 00:34:54 +05:30
custom_validate.py
dd_span_tagger.py feat(proxy): add key_alias, key_hash, requested_model DD APM span tags (#22710) 2026-03-03 20:22:59 -08:00
enterprise
health_check.py add docs and formatting 2026-02-28 14:08:09 +05:30
lambda.py
litellm_pre_call_utils.py [Feat] Add Tool Policies for AI Gateway (#22732) 2026-03-03 20:22:20 -08:00
llamaguard_prompt.txt
logo.jpg
mcp_registry.json fix: prompt registry 2026-02-18 00:34:54 +05:30
mcp_tools.py
model_config.yaml
openapi.json
post_call_rules.py
prisma_migration.py Revert "Fix/prisma schema permission (#19391)" 2026-01-21 17:19:32 +05:30
prometheus_cleanup.py Add Prometheus child_exit cleanup for gunicorn workers 2026-02-27 16:11:15 -08:00
proxy_cli.py Add Prometheus child_exit cleanup for gunicorn workers 2026-02-27 16:11:15 -08:00
proxy_config.yaml fix: prompt registry 2026-02-18 00:34:54 +05:30
proxy_server.py feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850) 2026-03-04 21:19:25 -08:00
README.md
route_llm_request.py feat(proxy): add WebSocket endpoint for responses API and route_llm_request support 2026-03-02 17:22:44 +05:30
schema.prisma feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850) 2026-03-04 21:19:25 -08:00
start.sh
utils.py [Feat] Add Tool Policies for AI Gateway (#22732) 2026-03-03 20:22:20 -08:00

litellm-proxy

A local, fast, and lightweight OpenAI-compatible server to call 100+ LLM APIs.

usage

$ pip install litellm
$ litellm --model ollama/codellama 

#INFO: Ollama running on http://0.0.0.0:8000

replace openai base

import openai # openai v1.0.0+
client = openai.OpenAI(api_key="anything",base_url="http://0.0.0.0:8000") # set proxy to base_url
# request sent to model set on litellm proxy, `litellm --model`
response = client.chat.completions.create(model="gpt-3.5-turbo", messages = [
    {
        "role": "user",
        "content": "this is a test request, write a short poem"
    }
])

print(response)

See how to call Huggingface,Bedrock,TogetherAI,Anthropic, etc.


Folder Structure

Routes

  • proxy_server.py - all openai-compatible routes - /v1/chat/completion, /v1/embedding + model info routes - /v1/models, /v1/model/info, /v1/model_group_info routes.
  • health_endpoints/ - /health, /health/liveliness, /health/readiness
  • management_endpoints/key_management_endpoints.py - all /key/* routes
  • management_endpoints/team_endpoints.py - all /team/* routes
  • management_endpoints/internal_user_endpoints.py - all /user/* routes
  • management_endpoints/ui_sso.py - all /sso/* routes