From 175c8c9cbc5251b527e26ddd865d90527366ba26 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 05:43:24 +0000 Subject: [PATCH 1/2] [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 5.28.0 --- .fern/metadata.json | 2 +- reference.md | 8 +++++ src/whop_sdk/users/__init__.py | 3 ++ src/whop_sdk/users/oauth_grants/__init__.py | 3 ++ src/whop_sdk/users/oauth_grants/client.py | 11 ++++++ src/whop_sdk/users/oauth_grants/raw_client.py | 16 +++++++++ .../users/oauth_grants/types/__init__.py | 3 ++ .../create_oauth_grants_request_mcp_client.py | 36 +++++++++++++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/whop_sdk/users/oauth_grants/types/create_oauth_grants_request_mcp_client.py diff --git a/.fern/metadata.json b/.fern/metadata.json index b45297c75..78055311d 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -15,7 +15,7 @@ "standardwebhooks": ">=1.0.1,<2" } }, - "originGitCommit": "71b6752138f9f4abe9e8f58724f614eb717ea242", + "originGitCommit": "b84de18966f48aec68d6e24ca19cf22a5afe0a9f", "originGitCommitIsDirty": false, "invokedBy": "ci", "requestedVersion": "2.2.0", diff --git a/reference.md b/reference.md index f8f85f88f..1fd8ea87d 100644 --- a/reference.md +++ b/reference.md @@ -49162,6 +49162,14 @@ client.users.oauth_grants.create(
+**mcp_client:** `typing.Optional[CreateOauthGrantsRequestMcpClient]` — The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + +
+
+ +
+
+ **nonce:** `typing.Optional[str]` — OIDC nonce, echoed into the resulting ID token. Required when `requested_scopes` includes `openid`.
diff --git a/src/whop_sdk/users/__init__.py b/src/whop_sdk/users/__init__.py index 8ea466546..9d1cd1df2 100644 --- a/src/whop_sdk/users/__init__.py +++ b/src/whop_sdk/users/__init__.py @@ -22,6 +22,7 @@ from . import oauth_grants, passkeys, preferences from .oauth_grants import ( CreateOauthGrantsRequestCodeChallengeMethod, + CreateOauthGrantsRequestMcpClient, CreateOauthGrantsRequestResponseType, ListOauthGrantsRequestDirection, ListOauthGrantsRequestOrder, @@ -43,6 +44,7 @@ "CheckAccessUsersResponse": ".types", "CheckAccessUsersResponseAccessLevel": ".types", "CreateOauthGrantsRequestCodeChallengeMethod": ".oauth_grants", + "CreateOauthGrantsRequestMcpClient": ".oauth_grants", "CreateOauthGrantsRequestResponseType": ".oauth_grants", "DeletePasskeysResponse": ".passkeys", "ListOauthGrantsRequestDirection": ".oauth_grants", @@ -95,6 +97,7 @@ def __dir__(): "CheckAccessUsersResponse", "CheckAccessUsersResponseAccessLevel", "CreateOauthGrantsRequestCodeChallengeMethod", + "CreateOauthGrantsRequestMcpClient", "CreateOauthGrantsRequestResponseType", "DeletePasskeysResponse", "ListOauthGrantsRequestDirection", diff --git a/src/whop_sdk/users/oauth_grants/__init__.py b/src/whop_sdk/users/oauth_grants/__init__.py index b0cb2a0d2..86d2fd40f 100644 --- a/src/whop_sdk/users/oauth_grants/__init__.py +++ b/src/whop_sdk/users/oauth_grants/__init__.py @@ -8,6 +8,7 @@ if typing.TYPE_CHECKING: from .types import ( CreateOauthGrantsRequestCodeChallengeMethod, + CreateOauthGrantsRequestMcpClient, CreateOauthGrantsRequestResponseType, ListOauthGrantsRequestDirection, ListOauthGrantsRequestOrder, @@ -16,6 +17,7 @@ ) _dynamic_imports: typing.Dict[str, str] = { "CreateOauthGrantsRequestCodeChallengeMethod": ".types", + "CreateOauthGrantsRequestMcpClient": ".types", "CreateOauthGrantsRequestResponseType": ".types", "ListOauthGrantsRequestDirection": ".types", "ListOauthGrantsRequestOrder": ".types", @@ -47,6 +49,7 @@ def __dir__(): __all__ = [ "CreateOauthGrantsRequestCodeChallengeMethod", + "CreateOauthGrantsRequestMcpClient", "CreateOauthGrantsRequestResponseType", "ListOauthGrantsRequestDirection", "ListOauthGrantsRequestOrder", diff --git a/src/whop_sdk/users/oauth_grants/client.py b/src/whop_sdk/users/oauth_grants/client.py index 769345926..ca580bcf6 100644 --- a/src/whop_sdk/users/oauth_grants/client.py +++ b/src/whop_sdk/users/oauth_grants/client.py @@ -8,6 +8,7 @@ from ...types.oauth_grant import OauthGrant from .raw_client import AsyncRawOauthGrantsClient, RawOauthGrantsClient from .types.create_oauth_grants_request_code_challenge_method import CreateOauthGrantsRequestCodeChallengeMethod +from .types.create_oauth_grants_request_mcp_client import CreateOauthGrantsRequestMcpClient from .types.create_oauth_grants_request_response_type import CreateOauthGrantsRequestResponseType from .types.list_oauth_grants_request_direction import ListOauthGrantsRequestDirection from .types.list_oauth_grants_request_order import ListOauthGrantsRequestOrder @@ -115,6 +116,7 @@ def create( code_challenge: typing.Optional[str] = OMIT, code_challenge_method: typing.Optional[CreateOauthGrantsRequestCodeChallengeMethod] = OMIT, consent_shown: typing.Optional[bool] = OMIT, + mcp_client: typing.Optional[CreateOauthGrantsRequestMcpClient] = OMIT, nonce: typing.Optional[str] = OMIT, response_type: typing.Optional[CreateOauthGrantsRequestResponseType] = OMIT, state: typing.Optional[str] = OMIT, @@ -146,6 +148,9 @@ def create( consent_shown : typing.Optional[bool] Whether the consent UI listed these scopes for the user. Sending `false` succeeds only when the user has already granted every scope requested, or when the app is one of Whop's own with the consent skip switched on and asks for `openid` alone. + mcp_client : typing.Optional[CreateOauthGrantsRequestMcpClient] + The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + nonce : typing.Optional[str] OIDC nonce, echoed into the resulting ID token. Required when `requested_scopes` includes `openid`. @@ -186,6 +191,7 @@ def create( code_challenge=code_challenge, code_challenge_method=code_challenge_method, consent_shown=consent_shown, + mcp_client=mcp_client, nonce=nonce, response_type=response_type, state=state, @@ -301,6 +307,7 @@ async def create( code_challenge: typing.Optional[str] = OMIT, code_challenge_method: typing.Optional[CreateOauthGrantsRequestCodeChallengeMethod] = OMIT, consent_shown: typing.Optional[bool] = OMIT, + mcp_client: typing.Optional[CreateOauthGrantsRequestMcpClient] = OMIT, nonce: typing.Optional[str] = OMIT, response_type: typing.Optional[CreateOauthGrantsRequestResponseType] = OMIT, state: typing.Optional[str] = OMIT, @@ -332,6 +339,9 @@ async def create( consent_shown : typing.Optional[bool] Whether the consent UI listed these scopes for the user. Sending `false` succeeds only when the user has already granted every scope requested, or when the app is one of Whop's own with the consent skip switched on and asks for `openid` alone. + mcp_client : typing.Optional[CreateOauthGrantsRequestMcpClient] + The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + nonce : typing.Optional[str] OIDC nonce, echoed into the resulting ID token. Required when `requested_scopes` includes `openid`. @@ -380,6 +390,7 @@ async def main() -> None: code_challenge=code_challenge, code_challenge_method=code_challenge_method, consent_shown=consent_shown, + mcp_client=mcp_client, nonce=nonce, response_type=response_type, state=state, diff --git a/src/whop_sdk/users/oauth_grants/raw_client.py b/src/whop_sdk/users/oauth_grants/raw_client.py index 28b046246..e3ca14cf4 100644 --- a/src/whop_sdk/users/oauth_grants/raw_client.py +++ b/src/whop_sdk/users/oauth_grants/raw_client.py @@ -10,6 +10,7 @@ from ...core.parse_error import ParsingError from ...core.pydantic_utilities import parse_obj_as from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError from ...errors.forbidden_error import ForbiddenError @@ -18,6 +19,7 @@ from ...types.oauth_grant import OauthGrant from ...types.v1error_response import V1ErrorResponse from .types.create_oauth_grants_request_code_challenge_method import CreateOauthGrantsRequestCodeChallengeMethod +from .types.create_oauth_grants_request_mcp_client import CreateOauthGrantsRequestMcpClient from .types.create_oauth_grants_request_response_type import CreateOauthGrantsRequestResponseType from .types.list_oauth_grants_request_direction import ListOauthGrantsRequestDirection from .types.list_oauth_grants_request_order import ListOauthGrantsRequestOrder @@ -171,6 +173,7 @@ def create( code_challenge: typing.Optional[str] = OMIT, code_challenge_method: typing.Optional[CreateOauthGrantsRequestCodeChallengeMethod] = OMIT, consent_shown: typing.Optional[bool] = OMIT, + mcp_client: typing.Optional[CreateOauthGrantsRequestMcpClient] = OMIT, nonce: typing.Optional[str] = OMIT, response_type: typing.Optional[CreateOauthGrantsRequestResponseType] = OMIT, state: typing.Optional[str] = OMIT, @@ -202,6 +205,9 @@ def create( consent_shown : typing.Optional[bool] Whether the consent UI listed these scopes for the user. Sending `false` succeeds only when the user has already granted every scope requested, or when the app is one of Whop's own with the consent skip switched on and asks for `openid` alone. + mcp_client : typing.Optional[CreateOauthGrantsRequestMcpClient] + The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + nonce : typing.Optional[str] OIDC nonce, echoed into the resulting ID token. Required when `requested_scopes` includes `openid`. @@ -229,6 +235,9 @@ def create( "code_challenge": code_challenge, "code_challenge_method": code_challenge_method, "consent_shown": consent_shown, + "mcp_client": convert_and_respect_annotation_metadata( + object_=mcp_client, annotation=CreateOauthGrantsRequestMcpClient, direction="write" + ), "nonce": nonce, "redirect_uri": redirect_uri, "requested_scopes": requested_scopes, @@ -462,6 +471,7 @@ async def create( code_challenge: typing.Optional[str] = OMIT, code_challenge_method: typing.Optional[CreateOauthGrantsRequestCodeChallengeMethod] = OMIT, consent_shown: typing.Optional[bool] = OMIT, + mcp_client: typing.Optional[CreateOauthGrantsRequestMcpClient] = OMIT, nonce: typing.Optional[str] = OMIT, response_type: typing.Optional[CreateOauthGrantsRequestResponseType] = OMIT, state: typing.Optional[str] = OMIT, @@ -493,6 +503,9 @@ async def create( consent_shown : typing.Optional[bool] Whether the consent UI listed these scopes for the user. Sending `false` succeeds only when the user has already granted every scope requested, or when the app is one of Whop's own with the consent skip switched on and asks for `openid` alone. + mcp_client : typing.Optional[CreateOauthGrantsRequestMcpClient] + The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + nonce : typing.Optional[str] OIDC nonce, echoed into the resulting ID token. Required when `requested_scopes` includes `openid`. @@ -520,6 +533,9 @@ async def create( "code_challenge": code_challenge, "code_challenge_method": code_challenge_method, "consent_shown": consent_shown, + "mcp_client": convert_and_respect_annotation_metadata( + object_=mcp_client, annotation=CreateOauthGrantsRequestMcpClient, direction="write" + ), "nonce": nonce, "redirect_uri": redirect_uri, "requested_scopes": requested_scopes, diff --git a/src/whop_sdk/users/oauth_grants/types/__init__.py b/src/whop_sdk/users/oauth_grants/types/__init__.py index 88d897d8d..f9bc53bcd 100644 --- a/src/whop_sdk/users/oauth_grants/types/__init__.py +++ b/src/whop_sdk/users/oauth_grants/types/__init__.py @@ -7,6 +7,7 @@ if typing.TYPE_CHECKING: from .create_oauth_grants_request_code_challenge_method import CreateOauthGrantsRequestCodeChallengeMethod + from .create_oauth_grants_request_mcp_client import CreateOauthGrantsRequestMcpClient from .create_oauth_grants_request_response_type import CreateOauthGrantsRequestResponseType from .list_oauth_grants_request_direction import ListOauthGrantsRequestDirection from .list_oauth_grants_request_order import ListOauthGrantsRequestOrder @@ -14,6 +15,7 @@ from .list_oauth_grants_response_page_info import ListOauthGrantsResponsePageInfo _dynamic_imports: typing.Dict[str, str] = { "CreateOauthGrantsRequestCodeChallengeMethod": ".create_oauth_grants_request_code_challenge_method", + "CreateOauthGrantsRequestMcpClient": ".create_oauth_grants_request_mcp_client", "CreateOauthGrantsRequestResponseType": ".create_oauth_grants_request_response_type", "ListOauthGrantsRequestDirection": ".list_oauth_grants_request_direction", "ListOauthGrantsRequestOrder": ".list_oauth_grants_request_order", @@ -45,6 +47,7 @@ def __dir__(): __all__ = [ "CreateOauthGrantsRequestCodeChallengeMethod", + "CreateOauthGrantsRequestMcpClient", "CreateOauthGrantsRequestResponseType", "ListOauthGrantsRequestDirection", "ListOauthGrantsRequestOrder", diff --git a/src/whop_sdk/users/oauth_grants/types/create_oauth_grants_request_mcp_client.py b/src/whop_sdk/users/oauth_grants/types/create_oauth_grants_request_mcp_client.py new file mode 100644 index 000000000..5ca62715e --- /dev/null +++ b/src/whop_sdk/users/oauth_grants/types/create_oauth_grants_request_mcp_client.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class CreateOauthGrantsRequestMcpClient(UniversalBaseModel): + """ + The downstream MCP client displayed on the consent screen. Requires explicit consent even when the upstream app already has a grant. Bound to the authorization code and returned on token exchange so the MCP server can verify the approved client. + """ + + client_id: str = pydantic.Field() + """ + The requesting MCP client's identifier. + """ + + client_name: str = pydantic.Field() + """ + The requesting MCP client's display name. + """ + + redirect_uri: str = pydantic.Field() + """ + The downstream redirect URI displayed to the user. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow From 1380f90f347ac020fcc84d3db08d8ab6798d2d13 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 05:43:25 +0000 Subject: [PATCH 2/2] [fern-replay] advance lockfile --- .fern/replay.lock | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.fern/replay.lock b/.fern/replay.lock index 6ea83476b..b130a4ab5 100644 --- a/.fern/replay.lock +++ b/.fern/replay.lock @@ -1758,5 +1758,11 @@ generations: cli_version: unknown generator_versions: fernapi/fern-python-sdk: 5.28.0 -current_generation: 3ad3a4a750c24660afd6338e165498f1bce2766a + - commit_sha: f663cbd9b6a5771dbd01481d560ed4bb33355658 + tree_hash: 4befc754f1915c2567d002523586e7b064c2089b + timestamp: 2026-10-05T05:43:20.575Z + cli_version: unknown + generator_versions: + fernapi/fern-python-sdk: 5.28.0 +current_generation: f663cbd9b6a5771dbd01481d560ed4bb33355658 patches: []