mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-17 23:51:30 +00:00
feat(mcp/v2): cover the full v1 MCPAuth surface in AuthSpecKind
The first cut declared only the five OAuth-grant-shaped modes, which silently dropped two live v1 auth_types: none (no upstream credential, the default for public upstreams) and aws_sigv4 (per-request SigV4 signing for Bedrock AgentCore-style upstreams). Neither had a home, so a server configured with them would have fallen through the resolver. Adds both as AuthSpecKind members with their resolve() arms (Phase 0 stubs), and records that the static-header family v1 splits across bearer_token/api_key/basic/token/authorization collapses into the single api_key mode with the scheme carried as a parameter rather than its own mode. The match-exhaustiveness gate forced the spike's label_enum to grow the two arms too, which is the gate doing its job.
This commit is contained in:
parent
3d2ef7472f
commit
d121a72f30
3 changed files with 32 additions and 6 deletions
|
|
@ -55,8 +55,11 @@ _spike_exhaustiveness.py:44:18 - error: Argument of type "Literal[AuthSpecKind.a
|
|||
assigned to parameter "arg" of type "Never" in function "assert_never" (reportArgumentType)
|
||||
```
|
||||
|
||||
Restore the arm and the errors disappear. This is why adding a sixth `AuthSpecKind` member without a
|
||||
`resolve()` arm fails the type gate rather than failing at runtime.
|
||||
Restore the arm and the errors disappear. This is why adding a new `AuthSpecKind` member without a
|
||||
`resolve()` arm fails the type gate rather than failing at runtime. `AuthSpecKind` covers v1's full
|
||||
`MCPAuth` surface: the three OAuth grants (`authorization_code`, `client_credentials`,
|
||||
`token_exchange`), the collapsed static-header family (`api_key`), client `passthrough`, `none`
|
||||
(no upstream auth), and `aws_sigv4` (per-request signing).
|
||||
|
||||
## Toolchain notes
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ def label_enum(kind: AuthSpecKind) -> str:
|
|||
return "static header"
|
||||
case AuthSpecKind.passthrough:
|
||||
return "client-forwarded"
|
||||
case AuthSpecKind.none:
|
||||
return "no upstream auth"
|
||||
case AuthSpecKind.aws_sigv4:
|
||||
return "aws sigv4 signing"
|
||||
# Reached only if an enum member has no arm above. basedpyright then narrows `kind` to that
|
||||
# uncovered member (not `Never`), so this `assert_never` is a type error => the gate bit.
|
||||
assert_never(kind)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,12 @@ from ..result import Error, Ok, Result
|
|||
class AuthSpecKind(str, Enum):
|
||||
"""The server's statically-declared upstream-auth mode — the single source of truth.
|
||||
|
||||
Canonical names follow the OAuth-grant vocabulary (see the Notion "resolve() Per-Mode
|
||||
Behavior" page). BYOK is *not* a member: it is the `api_key` mode seeded per-user, a
|
||||
source selector inside that arm.
|
||||
Covers v1's full `MCPAuth` surface, not only OAuth grants: the three grant modes, the
|
||||
collapsed static-header family, client passthrough, no-auth, and AWS request signing.
|
||||
BYOK is *not* a member: it is the `api_key` mode seeded per-user, a source selector
|
||||
inside that arm. The static-header schemes v1 splits into separate `MCPAuth` values
|
||||
(`bearer_token`/`api_key`/`basic`/`token`/`authorization`) collapse into `api_key`; the
|
||||
scheme is a parameter the arm carries, not its own mode.
|
||||
"""
|
||||
|
||||
authorization_code = (
|
||||
|
|
@ -47,8 +50,10 @@ class AuthSpecKind(str, Enum):
|
|||
)
|
||||
client_credentials = "client_credentials" # gateway service account (M2M)
|
||||
token_exchange = "token_exchange" # RFC 8693 on-behalf-of
|
||||
api_key = "api_key" # fixed/static header (BYOK = per-user-seeded source)
|
||||
api_key = "api_key" # static header, any scheme (BYOK = per-user-seeded source)
|
||||
passthrough = "passthrough" # client forwards an upstream-audience token
|
||||
none = "none" # no upstream credential; resolve yields a no-op auth, never an error
|
||||
aws_sigv4 = "aws_sigv4" # AWS SigV4 per-request signing (e.g. Bedrock AgentCore)
|
||||
|
||||
|
||||
@tagged_union(frozen=True)
|
||||
|
|
@ -163,6 +168,10 @@ class UpstreamCredentialProvider:
|
|||
return self._api_key(subject, server)
|
||||
case AuthSpecKind.passthrough:
|
||||
return self._passthrough(subject, server)
|
||||
case AuthSpecKind.none:
|
||||
return self._none(subject, server)
|
||||
case AuthSpecKind.aws_sigv4:
|
||||
return self._aws_sigv4(subject, server)
|
||||
|
||||
# --- arms: Phase 0 stubs (errors-as-values, no raise). Filled in Phase 1. -------------
|
||||
def _authorization_code(
|
||||
|
|
@ -190,6 +199,16 @@ class UpstreamCredentialProvider:
|
|||
) -> Result[httpx.Auth, CredError]:
|
||||
return _todo(AuthSpecKind.passthrough)
|
||||
|
||||
def _none(
|
||||
self, subject: Subject, server: ServerSpec
|
||||
) -> Result[httpx.Auth, CredError]:
|
||||
return _todo(AuthSpecKind.none)
|
||||
|
||||
def _aws_sigv4(
|
||||
self, subject: Subject, server: ServerSpec
|
||||
) -> Result[httpx.Auth, CredError]:
|
||||
return _todo(AuthSpecKind.aws_sigv4)
|
||||
|
||||
|
||||
def _todo(kind: AuthSpecKind) -> Result[httpx.Auth, CredError]:
|
||||
return Error(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue