diff --git a/Makefile b/Makefile index 99f67a3..faab597 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ VENV_PYTHON := $(VENV_DIR)/bin/python VENV_PIP := $(VENV_PYTHON) -m pip PROTO_REPO_URL := https://github.com/scalekit-inc/scalekit.git -PROTO_REF ?= v0.1.123.0 +PROTO_REF ?= v0.1.127.0 PROTO_SUBDIR := proto LOCAL_PROTO_REPO ?= ../scalekit diff --git a/scalekit/_version.py b/scalekit/_version.py index 80bde6c..eb5dcae 100644 --- a/scalekit/_version.py +++ b/scalekit/_version.py @@ -1,3 +1,3 @@ # Single source of truth for the SDK version. # Import this in setup.py and scalekit/core.py — never hardcode the version elsewhere. -__version__ = "2.10.0" \ No newline at end of file +__version__ = "2.11.0" \ No newline at end of file diff --git a/scalekit/actions/actions.py b/scalekit/actions/actions.py index 5af69a0..14df96f 100644 --- a/scalekit/actions/actions.py +++ b/scalekit/actions/actions.py @@ -1,3 +1,4 @@ +from datetime import timedelta from typing import Optional, Any, List, Dict, Union import requests from scalekit.actions.types import ToolRequest,ExecuteToolResponse,MagicLinkResponse,ListConnectedAccountsResponse,DeleteConnectedAccountResponse,GetConnectedAccountAuthResponse,GetConnectedAccountDetailsResponse,ToolInput, \ @@ -5,7 +6,8 @@ EnsureMcpInstanceResponse,UpdateMcpInstanceResponse,GetMcpInstanceResponse,ListMcpInstancesResponse,DeleteMcpInstanceResponse,GetMcpInstanceAuthStateResponse, \ McpConfig,McpConfigConnectionToolMapping,VerifyConnectedAccountUserResponse, \ CreateCustomProviderRequest,UpdateCustomProviderRequest,ListProvidersRequest,DeleteCustomProviderRequest, \ - CreateCustomProviderResponse,UpdateCustomProviderResponse,ListProvidersResponse,DeleteCustomProviderResponse + CreateCustomProviderResponse,UpdateCustomProviderResponse,ListProvidersResponse,DeleteCustomProviderResponse, \ + ListMcpConnectedAccountsResponse,CreateMcpSessionTokenResponse,McpConnectionAuthState from scalekit.actions.models.responses.create_connected_account_response import CreateConnectedAccountResponse from scalekit.actions.models.requests.create_connected_account_request import CreateConnectedAccountRequest from scalekit.actions.models.requests.update_connected_account_request import UpdateConnectedAccountRequest @@ -242,37 +244,35 @@ def verify_connected_account_user( return VerifyConnectedAccountUserResponse.from_proto(proto_response) def list_connected_accounts( - self, + self, connection_name: Optional[str] = None, identifier: Optional[str] = None, provider: Optional[str] = None, + connection_names: Optional[List[str]] = None, **kwargs ) -> ListConnectedAccountsResponse: + """List connected accounts with optional filtering. + + Args: + connection_name: Filter by a single connector slug, e.g. ``"github"``. + Mapped to the ``connector`` field in the underlying request. + identifier: Filter by end-user identifier, e.g. email or opaque user ID. + provider: Filter by OAuth/API-key provider slug, e.g. ``"google"``. + connection_names: Filter results to connected accounts belonging to *any* + of these connection slugs. Useful when you want to check multiple + connectors at once, e.g. ``["github", "google-calendar", "slack"]``. + Can be combined with ``identifier`` to narrow results to a specific user. + + Returns: + ListConnectedAccountsResponse containing the matching connected accounts. """ - List connected accounts with optional filtering - - :param connection_name: Connector identifier (optional) - :type: str - :param identifier: Identifier filter (optional) - :type: str - :param provider: Provider filter (optional) - :type: str - - :returns: - ListConnectedAccountsResponse containing list of connected accounts - """ - # Call the existing connected_accounts method which returns (response, metadata) tuple result_tuple = self.connected_accounts.list_connected_accounts( connector=connection_name, identifier=identifier, - provider=provider + provider=provider, + connection_names=connection_names, ) - - # Extract the response[0] (the actual ListConnectedAccountsResponse proto object) - proto_response = result_tuple[0] - - # Convert proto to our ListConnectedAccountsResponse class - return ListConnectedAccountsResponse.from_proto(proto_response) + return ListConnectedAccountsResponse.from_proto(result_tuple[0]) def delete_connected_account( self, @@ -543,6 +543,7 @@ def list_configs( filter_id: Optional[str] = None, filter_provider: Optional[str] = None, filter_name: Optional[str] = None, + filter_mcp_server_url: Optional[str] = None, search: Optional[str] = None, **kwargs, ) -> ListMcpConfigsResponse: @@ -554,6 +555,7 @@ def list_configs( filter_id=filter_id, filter_provider=filter_provider, filter_name=filter_name, + filter_mcp_server_url=filter_mcp_server_url, search=search, ) @@ -900,23 +902,43 @@ def list_configs( filter_id: Optional[str] = None, filter_provider: Optional[str] = None, filter_name: Optional[str] = None, + filter_mcp_server_url: Optional[str] = None, search: Optional[str] = None, ) -> ListMcpConfigsResponse: """List MCP configurations with optional pagination and filtering. Args: page_size: Maximum number of configs to include in the current page. - page_token: Cursor token returned by a previous `list_configs` call. - filter_id: Restrict results to a specific configuration identifier. - filter_provider: Restrict results to configs for a given provider slug. - filter_name: Restrict results to configs whose names match exactly. - search: Free-form search query applied to name field. + Defaults to the server-side default (typically 20). + page_token: Cursor token returned by a previous ``list_configs`` call. + Pass this to fetch the next page of results. + filter_id: Restrict results to a specific configuration by its Scalekit ID, + e.g. ``"cfg_01abc123"``. + filter_provider: Restrict results to configs for a given provider slug, + e.g. ``"github"`` or ``"google-calendar"``. + filter_name: Restrict results to configs whose name matches exactly, + e.g. ``"My GitHub Config"``. + filter_mcp_server_url: Restrict results to configs whose MCP server URL + matches this value, e.g. ``"https://mcp.example.com/sse"``. + search: Free-form search query applied to the config name field. Returns: - ListMcpConfigsResponse: Parsed wrapper around the proto response. + ListMcpConfigsResponse: Parsed wrapper around the proto response containing + a ``configs`` list, ``next_page_token``, and ``total_count``. Raises: ValueError: If an MCP client has not been configured on the action client. + + Example:: + + page1 = client.actions.mcp.list_configs(page_size=10) + for cfg in page1.configs: + print(cfg.name, cfg.mcp_server_url) + + if page1.next_page_token: + page2 = client.actions.mcp.list_configs( + page_size=10, page_token=page1.next_page_token + ) """ client = self._client() result_tuple = client.list_configs( @@ -925,6 +947,7 @@ def list_configs( filter_id=filter_id, filter_provider=filter_provider, filter_name=filter_name, + filter_mcp_server_url=filter_mcp_server_url, search=search, ) return ListMcpConfigsResponse.from_proto(result_tuple[0]) @@ -1160,6 +1183,146 @@ def get_instance_auth_state( ) return GetMcpInstanceAuthStateResponse.from_proto(result_tuple[0]) + def list_mcp_connected_accounts( + self, + config_id: str, + identifier: str, + include_auth_link: Optional[bool] = None, + ) -> ListMcpConnectedAccountsResponse: + """List the connected account auth state for all connections in an MCP config. + + For each connection defined in the MCP configuration, this method returns the + current authorisation status of the end-user's connected account and, + optionally, a one-time link the user can open to authorise or re-authorise + the connection. + + This is typically called server-side before serving MCP tool calls, to + determine whether the user still has valid credentials for every connector + the MCP config requires. + + Args: + config_id: Scalekit ID of the MCP configuration to inspect, + e.g. ``"cfg_01abc123"``. + identifier: End-user identifier for whom to fetch auth state — usually + an email address or opaque user ID that was used when calling + ``ensure_instance``, e.g. ``"alice@example.com"``. + include_auth_link: When ``True``, every connected account in the response + will include an ``authentication_link`` regardless of its current + status. Set this to ``True`` when building a connected-account + integration page for an MCP server — it lets the end user see the + status of all their connections and authorise or re-authorise any of + them in one pass. + + When ``False`` (default), ``authentication_link`` is omitted from + the response. If a connected account does not yet exist for a given + connection, ``connected_account_id`` will be an empty string. In + that situation you can either call ``get_authorization_link`` for + the specific connection or re-call this method with + ``include_auth_link=True``. + + **Auth links are valid for 1 minute only** — generate them close + to the time you redirect the user. + + Returns: + ListMcpConnectedAccountsResponse: Contains a ``connected_accounts`` list. + Each item is a :class:`McpConnectionAuthState` with fields: + + - ``connection_name`` — slug of the connector (``"github"``) + - ``provider`` — OAuth provider (``"github"``) + - ``connected_account_id`` — Scalekit ID for the user's connected account; + empty string if no connected account exists yet for this connection + - ``connected_account_status`` — ``"active"``, ``"expired"``, or ``"disconnected"`` + - ``authentication_link`` — auth/re-auth URL valid for 1 minute; + present for all connections when ``include_auth_link=True``, + otherwise omitted + + Raises: + ValueError: If ``config_id`` or ``identifier`` is blank. + + Example:: + + state = client.actions.mcp.list_mcp_connected_accounts( + config_id="cfg_01abc123", + identifier="alice@example.com", + include_auth_link=True, + ) + for account in state.connected_accounts: + if account.connected_account_status != "active": + print( + f"{account.connection_name} needs auth: " + f"{account.authentication_link}" + ) + """ + if not config_id: + raise ValueError("config_id is required") + if not identifier: + raise ValueError("identifier is required") + result_tuple = self._client().list_mcp_connected_accounts( + config_id=config_id, + identifier=identifier, + include_auth_link=include_auth_link, + ) + return ListMcpConnectedAccountsResponse.from_proto(result_tuple[0]) + + def create_session_token( + self, + mcp_config_id: str, + identifier: str, + expiry: Optional[timedelta] = None, + ) -> CreateMcpSessionTokenResponse: + """Create a short-lived session token for a user to access an MCP server. + + The token is scoped to a specific MCP configuration and end-user. Pass it + as a ``Bearer`` token in the ``Authorization`` header when making requests + to the MCP server URL associated with the config. + + Args: + mcp_config_id: Scalekit ID of the MCP configuration the token should + grant access to, e.g. ``"cfg_01abc123"``. + identifier: End-user identifier for whom the token is minted — typically + the same email or opaque ID used when calling ``ensure_instance``, + e.g. ``"alice@example.com"``. + expiry: Requested lifetime for the token as a Python ``timedelta``. + When omitted, the server-side default TTL is applied (typically + 1 hour). Example values: + + - ``timedelta(minutes=30)`` — 30-minute token + - ``timedelta(hours=8)`` — 8-hour token (work-day session) + - ``timedelta(days=1)`` — 24-hour token + + Returns: + CreateMcpSessionTokenResponse: Contains: + + - ``token`` (``str``) — opaque bearer token string. + - ``expires_at`` (``datetime``) — UTC datetime when the token expires. + + Raises: + ValueError: If ``mcp_config_id`` or ``identifier`` is blank. + + Example:: + + from datetime import timedelta + + resp = client.actions.mcp.create_session_token( + mcp_config_id="cfg_01abc123", + identifier="alice@example.com", + expiry=timedelta(hours=8), + ) + + headers = {"Authorization": f"Bearer {resp.token}"} + # Use headers when calling the MCP server URL + """ + if not mcp_config_id: + raise ValueError("mcp_config_id is required") + if not identifier: + raise ValueError("identifier is required") + result_tuple = self._client().create_session_token( + mcp_config_id=mcp_config_id, + identifier=identifier, + expiry=expiry, + ) + return CreateMcpSessionTokenResponse.from_proto(result_tuple[0]) + class ActionProviders: """Typed action layer over ProvidersClient for custom provider CRUD. diff --git a/scalekit/actions/models/mcp_config.py b/scalekit/actions/models/mcp_config.py index 0daa611..4cb7b88 100644 --- a/scalekit/actions/models/mcp_config.py +++ b/scalekit/actions/models/mcp_config.py @@ -74,6 +74,10 @@ class McpConfig(BaseModel): default_factory=list, description="Mappings that connect tools to underlying connections", ) + mcp_server_url: Optional[str] = Field( + None, + description="URL of the MCP server endpoint associated with this config (read-only)", + ) def to_proto(self) -> ProtoMcpConfig: """Convert the model into a protobuf MCP config.""" @@ -117,6 +121,7 @@ def from_proto(cls, proto_config: ProtoMcpConfig) -> "McpConfig": McpConfigConnectionToolMapping.from_proto(mapping) for mapping in proto_config.connection_tool_mappings ], + mcp_server_url=proto_config.mcp_server_url or None, ) def to_dict(self) -> dict: @@ -129,6 +134,7 @@ def to_dict(self) -> dict: "connection_tool_mappings": [ mapping.model_dump() for mapping in self.connection_tool_mappings ], + "mcp_server_url": self.mcp_server_url, } class Config: diff --git a/scalekit/actions/models/mcp_connection_auth_state.py b/scalekit/actions/models/mcp_connection_auth_state.py new file mode 100644 index 0000000..2d42045 --- /dev/null +++ b/scalekit/actions/models/mcp_connection_auth_state.py @@ -0,0 +1,62 @@ +from typing import Optional + +from pydantic import BaseModel, Field + +from scalekit.v1.mcp.mcp_pb2 import McpConnectionAuthState as ProtoMcpConnectionAuthState + + +class McpConnectionAuthState(BaseModel): + """Authentication status for a single connection within an MCP config. + + Returned by ``list_mcp_connected_accounts`` to show whether each connection + backing an MCP configuration is authorised for a given user identifier. + + Attributes: + connection_id: Internal Scalekit identifier for the connection. + connection_name: Slug name of the connection, e.g. ``"github"``. + provider: OAuth/API-key provider backing the connection, e.g. ``"github"``. + connected_account_id: Scalekit identifier for the user's connected account, + if one exists. + connected_account_status: Current authorisation status of the connected + account. Common values: ``"active"``, ``"expired"``, ``"disconnected"``. + authentication_link: One-time URL the end-user can open to authorise or + re-authorise the connection. Only populated when ``include_auth_link`` + was ``True`` in the request and the account is not currently active. + """ + + connection_id: Optional[str] = Field(None, description="Internal connection identifier") + connection_name: Optional[str] = Field(None, description="Slug name of the connection") + provider: Optional[str] = Field(None, description="Provider backing the connection") + connected_account_id: Optional[str] = Field(None, description="Scalekit connected account ID") + connected_account_status: Optional[str] = Field( + None, + description="Authorisation status: 'active', 'expired', 'disconnected'", + ) + authentication_link: Optional[str] = Field( + None, + description="One-time auth URL; only present when include_auth_link=True and account is not active", + ) + + @classmethod + def from_proto(cls, proto_state: ProtoMcpConnectionAuthState) -> "McpConnectionAuthState": + return cls( + connection_id=proto_state.connection_id or None, + connection_name=proto_state.connection_name or None, + provider=proto_state.provider or None, + connected_account_id=proto_state.connected_account_id or None, + connected_account_status=proto_state.connected_account_status or None, + authentication_link=proto_state.authentication_link or None, + ) + + def to_dict(self) -> dict: + return { + "connection_id": self.connection_id, + "connection_name": self.connection_name, + "provider": self.provider, + "connected_account_id": self.connected_account_id, + "connected_account_status": self.connected_account_status, + "authentication_link": self.authentication_link, + } + + class Config: + validate_assignment = True diff --git a/scalekit/actions/models/responses/create_mcp_session_token_response.py b/scalekit/actions/models/responses/create_mcp_session_token_response.py new file mode 100644 index 0000000..4494515 --- /dev/null +++ b/scalekit/actions/models/responses/create_mcp_session_token_response.py @@ -0,0 +1,52 @@ +from datetime import datetime +from typing import Optional + +from pydantic import BaseModel, Field + + +class CreateMcpSessionTokenResponse(BaseModel): + """Response from ``create_session_token``. + + A short-lived session token that an end-user or service can use to + authenticate against an MCP server endpoint. + + Attributes: + token: Opaque bearer token string. Pass this as the ``Authorization`` + header value (``Bearer ``) when calling the MCP server URL. + expires_at: UTC datetime at which the token becomes invalid. Your + application should refresh before this time. + + Example:: + + from datetime import timedelta + + resp = client.actions.mcp.create_session_token( + mcp_config_id="cfg_abc123", + identifier="user@example.com", + expiry=timedelta(hours=8), + ) + print(resp.token) # "eyJ..." + print(resp.expires_at) # 2026-06-03 20:00:00 + """ + + token: Optional[str] = Field(None, description="Bearer token for MCP server authentication") + expires_at: Optional[datetime] = Field(None, description="UTC expiry time for the token") + + @classmethod + def from_proto(cls, proto_response) -> "CreateMcpSessionTokenResponse": + expires_at = None + if proto_response.HasField("expires_at"): + expires_at = proto_response.expires_at.ToDatetime() + return cls( + token=proto_response.token or None, + expires_at=expires_at, + ) + + def to_dict(self) -> dict: + return { + "token": self.token, + "expires_at": self.expires_at.isoformat() if self.expires_at else None, + } + + class Config: + validate_assignment = True diff --git a/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py b/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py new file mode 100644 index 0000000..7ab2945 --- /dev/null +++ b/scalekit/actions/models/responses/list_mcp_connected_accounts_response.py @@ -0,0 +1,52 @@ +from typing import List + +from pydantic import BaseModel, Field + +from scalekit.actions.models.mcp_connection_auth_state import McpConnectionAuthState + + +class ListMcpConnectedAccountsResponse(BaseModel): + """Response from ``list_mcp_connected_accounts``. + + Contains the per-connection authentication state for every connection + that is part of the requested MCP configuration, for a specific user + identifier. + + Attributes: + connected_accounts: One entry per connection in the MCP config. Each + entry carries the connection name, provider, the user's connected + account ID/status, and optionally an auth link if the account is + not active and ``include_auth_link`` was requested. + + Example:: + + response = client.actions.mcp.list_mcp_connected_accounts( + config_id="cfg_abc123", + identifier="user@example.com", + include_auth_link=True, + ) + for account in response.connected_accounts: + if account.connected_account_status != "active": + print(f"Re-auth needed for {account.connection_name}: {account.authentication_link}") + """ + + connected_accounts: List[McpConnectionAuthState] = Field( + default_factory=list, + description="Auth state per connection in the MCP config", + ) + + @classmethod + def from_proto(cls, proto_response) -> "ListMcpConnectedAccountsResponse": + connected_accounts = [ + McpConnectionAuthState.from_proto(proto_state) + for proto_state in getattr(proto_response, "connected_accounts", []) + ] + return cls(connected_accounts=connected_accounts) + + def to_dict(self) -> dict: + return { + "connected_accounts": [account.to_dict() for account in self.connected_accounts], + } + + class Config: + validate_assignment = True diff --git a/scalekit/actions/types.py b/scalekit/actions/types.py index 0e37654..335dfb9 100644 --- a/scalekit/actions/types.py +++ b/scalekit/actions/types.py @@ -35,6 +35,9 @@ from .models.responses.update_custom_provider_response import UpdateCustomProviderResponse from .models.responses.list_providers_response import ListProvidersResponse from .models.responses.delete_custom_provider_response import DeleteCustomProviderResponse +from .models.responses.list_mcp_connected_accounts_response import ListMcpConnectedAccountsResponse +from .models.responses.create_mcp_session_token_response import CreateMcpSessionTokenResponse +from .models.mcp_connection_auth_state import McpConnectionAuthState __all__ = [ @@ -82,4 +85,7 @@ 'ListProvidersResponse', 'DeleteCustomProviderResponse', 'VerifyConnectedAccountUserResponse', + 'ListMcpConnectedAccountsResponse', + 'CreateMcpSessionTokenResponse', + 'McpConnectionAuthState', ] diff --git a/scalekit/connected_accounts.py b/scalekit/connected_accounts.py index 99bb068..457bce1 100644 --- a/scalekit/connected_accounts.py +++ b/scalekit/connected_accounts.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import List, Optional from scalekit.core import CoreClient from scalekit.v1.connected_accounts.connected_accounts_pb2 import ( @@ -47,7 +47,8 @@ def list_connected_accounts( identifier: Optional[str] = None, provider: Optional[str] = None, page_size: Optional[int] = None, - page_token: Optional[str] = None + page_token: Optional[str] = None, + connection_names: Optional[List[str]] = None, ) -> ListConnectedAccountsResponse: """ Method to list connected accounts for a user @@ -66,21 +67,28 @@ def list_connected_accounts( :type : ``` int ``` :param page_token : Page token for pagination (optional) :type : ``` str ``` + :param connection_names : Filter results to only connected accounts belonging to these + connection names (optional). Each entry is the slug name of + a connector, e.g. ``["github", "google-calendar"]``. + :type : ``` List[str] ``` :returns: List Connected Accounts Response """ + request = ListConnectedAccountsRequest( + organization_id=organization_id, + user_id=user_id, + connector=connector, + identifier=identifier, + provider=provider, + page_size=page_size, + page_token=page_token, + ) + if connection_names: + request.connection_names.extend(connection_names) return self.core_client.grpc_exec( self.connected_accounts_service.ListConnectedAccounts.with_call, - ListConnectedAccountsRequest( - organization_id=organization_id, - user_id=user_id, - connector=connector, - identifier=identifier, - provider=provider, - page_size=page_size, - page_token=page_token - ), + request, ) def create_connected_account( diff --git a/scalekit/core.py b/scalekit/core.py index 5180ac4..e69e60b 100644 --- a/scalekit/core.py +++ b/scalekit/core.py @@ -29,7 +29,7 @@ class CoreClient: sdk_version = f"Scalekit-Python/{_sdk_version}" # YYYYMMDD - api_version = "20260513" + api_version = "20260603" user_agent = f"{sdk_version} Python/{platform.python_version()} ({platform.system()}; {platform.architecture()}" def __init__(self, env_url, client_id, client_secret): diff --git a/scalekit/mcp.py b/scalekit/mcp.py index 2829cec..bcee282 100644 --- a/scalekit/mcp.py +++ b/scalekit/mcp.py @@ -1,5 +1,8 @@ +from datetime import timedelta from typing import Optional, List +from google.protobuf.duration_pb2 import Duration + from scalekit.core import CoreClient from scalekit.v1.mcp.mcp_pb2 import * from scalekit.v1.mcp.mcp_pb2_grpc import McpServiceStub @@ -29,33 +32,37 @@ def list_configs( filter_id: Optional[str] = None, filter_provider: Optional[str] = None, filter_name: Optional[str] = None, + filter_mcp_server_url: Optional[str] = None, search: Optional[str] = None, ) -> ListMcpConfigsResponse: """ Method to list MCP Configurations with optional filters - :param page_size : Number of items per page - :type : ``` int ``` - :param page_token : Token for the page to retrieve - :type : ``` str ``` - :param filter_id : Filter by MCP Config ID - :type : ``` str ``` - :param filter_provider : Filter by provider - :type : ``` str ``` - :param filter_name : Filter by name - :type : ``` str ``` - :param search : Search term - :type : ``` str ``` + :param page_size : Number of items per page + :type : ``` int ``` + :param page_token : Token for the page to retrieve + :type : ``` str ``` + :param filter_id : Filter by MCP Config ID + :type : ``` str ``` + :param filter_provider : Filter by provider slug + :type : ``` str ``` + :param filter_name : Filter by config name (exact match) + :type : ``` str ``` + :param filter_mcp_server_url : Filter configs whose MCP server URL matches this value + :type : ``` str ``` + :param search : Free-form search term applied to the name field + :type : ``` str ``` :returns: List MCP Configs Response """ filter_obj = None - if any(x is not None for x in (filter_id, filter_provider, filter_name, search)): + if any(x is not None for x in (filter_id, filter_provider, filter_name, filter_mcp_server_url, search)): filter_obj = ListMcpConfigsRequest.Filter( id=filter_id or "", provider=filter_provider or "", name=filter_name or "", + mcp_server_url=filter_mcp_server_url or "", ) return self.core_client.grpc_exec( @@ -227,3 +234,87 @@ def get_instance_auth_state( self.mcp_service.GetMcpInstanceAuthState.with_call, request, ) + + def list_mcp_connected_accounts( + self, + config_id: str, + identifier: str, + include_auth_link: Optional[bool] = None, + ) -> ListMcpConnectedAccountsResponse: + """ + List the connected account auth state for all connections in an MCP config + for a given user identifier. + + :param config_id : ID of the MCP configuration whose connections to inspect + :type : ``` str ``` + :param identifier : End-user identifier (e.g. email or opaque user ID) for + whom the connected account state is being fetched + :type : ``` str ``` + :param include_auth_link : When True, every connected account in the response will + include an ``authentication_link`` field regardless of its + current status. Set this to True when you are building a + connected-account integration page for an MCP server and + want the end user to see the status of all their connections + and be able to authorise or re-authorise any of them. + + When False (default), ``authentication_link`` is omitted. + If a connected account does not exist for a connection, + ``connected_account_id`` will be an empty string. To + generate an auth link in that case, either call + ``get_authorization_link`` for the specific connection or + re-call this method with ``include_auth_link=True``. + + Note: generated auth links are valid for 1 minute only. + :type : ``` bool ``` + + :returns: + ListMcpConnectedAccountsResponse + """ + request = ListMcpConnectedAccountsRequest( + config_id=config_id, + identifier=identifier, + ) + if include_auth_link is not None: + request.include_auth_link = include_auth_link + + return self.core_client.grpc_exec( + self.mcp_service.ListMcpConnectedAccounts.with_call, + request, + ) + + def create_session_token( + self, + mcp_config_id: str, + identifier: str, + expiry: Optional[timedelta] = None, + ) -> CreateMcpSessionTokenResponse: + """ + Create a short-lived session token for a user to authenticate against an MCP server. + + :param mcp_config_id : ID of the MCP configuration the session token is scoped to + :type : ``` str ``` + :param identifier : End-user identifier (e.g. email or opaque user ID) for whom + the token is being minted + :type : ``` str ``` + :param expiry : Lifetime of the token as a Python ``timedelta``. When omitted, + the server-side default TTL is applied. + Example: ``timedelta(hours=1)`` + :type : ``` timedelta ``` + + :returns: + CreateMcpSessionTokenResponse — contains ``token`` (str) and ``expires_at`` (Timestamp) + """ + request = CreateMcpSessionTokenRequest( + mcp_config_id=mcp_config_id, + identifier=identifier, + ) + if expiry is not None: + duration = Duration() + total_seconds = int(expiry.total_seconds()) + duration.seconds = total_seconds + request.expiry.CopyFrom(duration) + + return self.core_client.grpc_exec( + self.mcp_service.CreateMcpSessionToken.with_call, + request, + ) diff --git a/scalekit/v1/connected_accounts/connected_accounts_pb2.py b/scalekit/v1/connected_accounts/connected_accounts_pb2.py index a2f7fb8..48dbda9 100644 --- a/scalekit/v1/connected_accounts/connected_accounts_pb2.py +++ b/scalekit/v1/connected_accounts/connected_accounts_pb2.py @@ -22,7 +22,7 @@ from scalekit.v1.options import options_pb2 as scalekit_dot_v1_dot_options_dot_options__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n7scalekit/v1/connected_accounts/connected_accounts.proto\x12\x1escalekit.v1.connected_accounts\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a!scalekit/v1/options/options.proto\"\x99\x0c\n\x1cListConnectedAccountsRequest\x12\xb1\x01\n\x0forganization_id\x18\x01 \x01(\tB\x82\x01\x92\x41v2]Filter by organization ID. Returns only connected accounts associated with this organization.J\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12\x91\x01\n\x07user_id\x18\x02 \x01(\tBs\x92\x41g2MFilter by user ID. Returns only connected accounts associated with this user.J\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdf\x01\n\tconnector\x18\x03 \x01(\tB\xbb\x01\x92\x41\x99\x01\x32\x8c\x01\x46ilter by connector type (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xdb\x01\n\nidentifier\x18\x04 \x01(\tB\xb5\x01\x92\x41\xa8\x01\x32\x91\x01\x46ilter by account identifier. The unique identifier for the connected account within the third-party service (e.g., email address, workspace ID).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12\x9d\x01\n\x08provider\x18\x05 \x01(\tB\x80\x01\x92\x41t2hFilter by OAuth provider. The authentication provider name such as \'google\', \'microsoft\', \'github\', etc.J\x08\"google\"\xbaH\x06r\x04\x10\x00\x18\x32R\x08provider\x12\x9b\x01\n\tpage_size\x18\x06 \x01(\rB~\x92\x41r2lMaximum number of connected accounts to return per page. Must be between 0 and 100. Default is typically 10.J\x02\x31\x30\xbaH\x06*\x04\x10\x64(\x00R\x08pageSize\x12\xcb\x01\n\npage_token\x18\x07 \x01(\tB\xab\x01\x92\x41\x9e\x01\x32\x83\x01Pagination token from a previous response. Use the next_page_token value from ListConnectedAccountsResponse to fetch the next page.J\x16\"eyJvZmZzZXQiOjEwfQ==\"\xbaH\x06r\x04\x10\x00\x18\x64R\tpageToken\x12\xa7\x01\n\x05query\x18\x08 \x01(\tB\x90\x01\x92\x41\x83\x01\x32qText search query to filter connected accounts by name, identifier, or other searchable fields. Case-insensitive.J\x0e\"john@example\"\xbaH\x06r\x04\x10\x00\x18\x64R\x05queryB\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifier\"\xbb\x06\n\x1dListConnectedAccountsResponse\x12\xdc\x01\n\x12\x63onnected_accounts\x18\x01 \x03(\x0b\x32\x37.scalekit.v1.connected_accounts.ConnectedAccountForListBt\x92\x41q2oList of connected accounts matching the filter criteria. Excludes sensitive authorization details for security.R\x11\x63onnectedAccounts\x12\x99\x01\n\ntotal_size\x18\x02 \x01(\rBz\x92\x41w2pTotal count of connected accounts matching the filter criteria across all pages. Use for calculating pagination.J\x03\x31\x30\x30R\ttotalSize\x12\xd2\x01\n\x0fnext_page_token\x18\x03 \x01(\tB\xa9\x01\x92\x41\x9c\x01\x32\x81\x01Pagination token for retrieving the next page. Empty if this is the last page. Pass this value to page_token in the next request.J\x16\"eyJvZmZzZXQiOjIwfQ==\"\xbaH\x06r\x04\x10\x00\x18 R\rnextPageToken\x12\xc9\x01\n\x0fprev_page_token\x18\x04 \x01(\tB\xa0\x01\x92\x41\x93\x01\x32}Pagination token for retrieving the previous page. Empty if this is the first page. Pass this value to page_token to go back.J\x12\"eyJvZmZzZXQiOjB9\"\xbaH\x06r\x04\x10\x00\x18 R\rprevPageToken\"\xe0\x06\n\x1eSearchConnectedAccountsRequest\x12\xb9\x01\n\x05query\x18\x01 \x01(\tB\xa2\x01\x92\x41\x91\x01\x32\x86\x01Search term to match against connected account identifiers, providers, or connectors. Must be at least 3 characters. Case insensitive.J\x06google\xbaH\nr\x05\x10\x03\x18\xc8\x01\xc8\x01\x01R\x05query\x12\x85\x01\n\tpage_size\x18\x02 \x01(\rBh\x92\x41^2XMaximum number of connected accounts to return per page. Value must be between 1 and 30.J\x02\x33\x30\xbaH\x04*\x02\x18\x1eR\x08pageSize\x12\xa5\x01\n\npage_token\x18\x03 \x01(\tB\x85\x01\x92\x41\x81\x01\x32\x61Token from a previous response for pagination. Provide this to retrieve the next page of results.J\x1c\x65yJwYWdlIjoyLCJsaW1pdCI6MzB9R\tpageToken\x12i\n\rconnection_id\x18\x04 \x01(\tBD\x92\x41\x38\x32*Connection ID to filter connected accountsJ\n\"conn_123\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionId:\xe6\x01\x92\x41\xe2\x01\n\x9c\x01*\x19Search Connected Accounts2\x7fSearch for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors2Aquery=google&page_size=30&page_token=eyJwYWdlIjoyLCJsaW1pdCI6MzB9\"\x87\x05\n\x1fSearchConnectedAccountsResponse\x12\xcc\x01\n\x12\x63onnected_accounts\x18\x01 \x03(\x0b\x32\x37.scalekit.v1.connected_accounts.ConnectedAccountForListBd\x92\x41\x61\x32_List of connected accounts matching the search query. Excludes sensitive authorization details.R\x11\x63onnectedAccounts\x12l\n\ntotal_size\x18\x02 \x01(\rBM\x92\x41J2CTotal count of accounts matching the search query across all pages.J\x03\x31\x30\x30R\ttotalSize\x12\x91\x01\n\x0fnext_page_token\x18\x03 \x01(\tBi\x92\x41]2CPagination token for the next page. Empty if this is the last page.J\x16\"eyJvZmZzZXQiOjMwfQ==\"\xbaH\x06r\x04\x10\x00\x18 R\rnextPageToken\x12\x92\x01\n\x0fprev_page_token\x18\x04 \x01(\tBj\x92\x41^2HPagination token for the previous page. Empty if this is the first page.J\x12\"eyJvZmZzZXQiOjB9\"\xbaH\x06r\x04\x10\x00\x18 R\rprevPageToken\"\xa0\x08\n\x1d\x43reateConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12\xbd\x02\n\x11\x63onnected_account\x18\x05 \x01(\x0b\x32\x36.scalekit.v1.connected_accounts.CreateConnectedAccountB\xd7\x01\x92\x41\xcd\x01\x32*Details of the connected account to createJ\x9e\x01{ \"authorization_type\": \"OAUTH2\", \"authorization_details\": { \"oauth_token\": { \"access_token\": \"...\", \"refresh_token\": \"...\", \"scopes\": [\"read\", \"write\"] } } }\xbaH\x03\xc8\x01\x01R\x10\x63onnectedAccountB\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifier\"\x8d\x02\n\x1e\x43reateConnectedAccountResponse\x12\xea\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB\x8a\x01\x92\x41\x86\x01\x32\x83\x01The newly created connected account with its unique identifier, status, and complete authorization details including access tokens.R\x10\x63onnectedAccount\"\x90\t\n\x1dUpdateConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12g\n\x02id\x18\x06 \x01(\tBR\x92\x41\x41\x32\x35Unique identifier for the connected account to updateJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x12\xbd\x02\n\x11\x63onnected_account\x18\x05 \x01(\x0b\x32\x36.scalekit.v1.connected_accounts.UpdateConnectedAccountB\xd7\x01\x92\x41\xcd\x01\x32*Details of the connected account to updateJ\x9e\x01{ \"authorization_type\": \"OAUTH2\", \"authorization_details\": { \"oauth_token\": { \"access_token\": \"...\", \"refresh_token\": \"...\", \"scopes\": [\"read\", \"write\"] } } }\xbaH\x03\xc8\x01\x01R\x10\x63onnectedAccountB\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\"\xf7\x01\n\x1eUpdateConnectedAccountResponse\x12\xd4\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountBu\x92\x41r2pThe updated connected account with refreshed credentials, new token expiry, and modified configuration settings.R\x10\x63onnectedAccount\"\xd0\x06\n\x1d\x44\x65leteConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12g\n\x02id\x18\x05 \x01(\tBR\x92\x41\x41\x32\x35Unique identifier for the connected account to deleteJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\" \n\x1e\x44\x65leteConnectedAccountResponse\"\xdf\t\n&GetMagicLinkForConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12]\n\x02id\x18\x05 \x01(\tBH\x92\x41\x37\x32+Unique identifier for the connected accountJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x12\xcf\x01\n\x05state\x18\x07 \x01(\tB\xb3\x01\x92\x41\xa5\x01\x32wOptional opaque state value. State added to the user verify redirect URL query params to validate the user verificationJ*\"QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=\"\xbaH\x07r\x05\x10\x00\x18\x80\x04H\x05R\x05state\x88\x01\x01\x12\x9d\x01\n\x0fuser_verify_url\x18\x08 \x01(\tBp\x92\x41T2\"B2B app\'s user verify redirect URLJ.\"https://app.yourapp.com/user/verify/callback\"\xbaH\x16r\x14\x10\x00\x18\x80\x10\x32\r^$|^https?://H\x06R\ruserVerifyUrl\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_idB\x08\n\x06_stateB\x12\n\x10_user_verify_url\"\x9c\x02\n\'GetMagicLinkForConnectedAccountResponse\x12r\n\x04link\x18\x01 \x01(\tB^\x92\x41[2%Authentication link for the connectorJ2\"https://notion.com/oauth/authorize?client_id=...\"R\x04link\x12}\n\x06\x65xpiry\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampBI\x92\x41\x46\x32,Expiry timestamp for the authentication linkJ\x16\"2024-03-20T15:04:05Z\"R\x06\x65xpiry\"\xeb\x02\n!VerifyConnectedAccountUserRequest\x12\xc8\x01\n\x0f\x61uth_request_id\x18\x01 \x01(\tB\x9f\x01\x92\x41\x8e\x01\x32`Auth request ID as base64url-encoded opaque token from the user verify redirect URL query paramsJ*\"QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=\"\xe0\x41\x02\xbaH\x07r\x05\x10\x01\x18\xe8\x07R\rauthRequestId\x12{\n\nidentifier\x18\x02 \x01(\tB[\x92\x41K25Current logged in user\'s connected account identifierJ\x12\"user@example.com\"\xe0\x41\x02\xbaH\x07r\x05\x10\x01\x18\xc8\x01R\nidentifier\"\xd3\x01\n\"VerifyConnectedAccountUserResponse\x12\xac\x01\n\x1dpost_user_verify_redirect_url\x18\x01 \x01(\tBj\x92\x41g29URL to redirect the user to after successful verificationJ*\"https://env1.example.com/connect/success\"R\x19postUserVerifyRedirectUrl\"\xcf\x06\n&GetConnectedAccountByIdentifierRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12]\n\x02id\x18\x05 \x01(\tBH\x92\x41\x37\x32+Unique identifier for the connected accountJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\"\xbe\x02\n\'GetConnectedAccountByIdentifierResponse\x12\x92\x02\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB\xb2\x01\x92\x41\xae\x01\x32\xab\x01The connected account with complete details including sensitive authorization credentials (access tokens, refresh tokens, scopes). Handle with appropriate access controls.R\x10\x63onnectedAccount\"\xe3\x13\n\x10\x43onnectedAccount\x12\xbc\x01\n\nidentifier\x18\x01 \x01(\tB\x9b\x01\x92\x41\x97\x01\x32\x80\x01The unique identifier for this account in the third-party service. Typically an email address, user ID, or workspace identifier.J\x12\"user@example.com\"R\nidentifier\x12\xaa\x01\n\x08provider\x18\x02 \x01(\tB\x8d\x01\x92\x41\x89\x01\x32}OAuth provider name (e.g., \'google\', \'microsoft\', \'github\'). Identifies which authentication service manages this connection.J\x08\"google\"R\x08provider\x12\xe4\x01\n\x06status\x18\x03 \x01(\x0e\x32/.scalekit.v1.connected_accounts.ConnectorStatusB\x9a\x01\x92\x41\x96\x01\x32\x93\x01\x43urrent status of the connected account. Indicates if the account is active, expired, pending authorization, or pending user identity verification.R\x06status\x12\xe9\x01\n\x12\x61uthorization_type\x18\x04 \x01(\x0e\x32-.scalekit.v1.connected_accounts.ConnectorTypeB\x8a\x01\x92\x41\x86\x01\x32\x83\x01Type of authorization mechanism used. Specifies whether this connection uses OAuth, API keys, bearer tokens, or other auth methods.R\x11\x61uthorizationType\x12\x81\x02\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\x95\x01\x92\x41\x91\x01\x32\x8e\x01Sensitive authentication credentials including access tokens, refresh tokens, and scopes. Contains either OAuth tokens or static auth details.R\x14\x61uthorizationDetails\x12\xce\x01\n\x10token_expires_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x87\x01\x92\x41\x83\x01\x32iExpiration timestamp for the access token. After this time, the token must be refreshed or re-authorized.J\x16\"2024-12-31T23:59:59Z\"R\x0etokenExpiresAt\x12\xc9\x01\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x8d\x01\x92\x41\x89\x01\x32oTimestamp when this connected account was last modified. Updated whenever credentials or configuration changes.J\x16\"2024-03-20T15:04:05Z\"R\tupdatedAt\x12\xae\x01\n\tconnector\x18\x08 \x01(\tB\x8f\x01\x92\x41\x8b\x01\x32\x7f\x43onnector identifier (e.g., \'notion\', \'slack\', \'salesforce\'). Indicates which third-party application this account connects to.J\x08\"notion\"R\tconnector\x12\xcd\x01\n\x0clast_used_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x8e\x01\x92\x41\x8a\x01\x32pTimestamp when this connected account was last used to make an API call. Useful for tracking active connections.J\x16\"2024-03-20T14:30:00Z\"R\nlastUsedAt\x12\x98\x01\n\x02id\x18\n \x01(\tB\x87\x01\x92\x41v2\\Unique Scalekit-generated identifier for this connected account. Always prefixed with \'ca_\'.J\x16\"ca_24834495392086178\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_R\x02id\x12\xc6\x01\n\rconnection_id\x18\x0b \x01(\tB\xa0\x01\x92\x41\x93\x01\x32wReference to the parent connection configuration. Links this account to a specific connector setup in your environment.J\x18\"conn_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionId\x12\x89\x02\n\napi_config\x18\x0c \x01(\x0b\x32\x17.google.protobuf.StructB\xd0\x01\x92\x41\xcc\x01\x32xOptional JSON configuration for connector-specific API settings such as rate limits, custom endpoints, or feature flags.JP{\"rate_limit\": 1000, \"timeout\": 30, \"base_url\": \"https://api.custom-domain.com\"}R\tapiConfig\"\x9a\x06\n\x16\x43reateConnectedAccount\x12\xae\x03\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\xc2\x02\x92\x41\xbe\x02\x32\xcd\x01Optional authentication credentials for the connected account. Include OAuth tokens (access_token, refresh_token, scopes) or static auth details (API keys, bearer tokens). Can be provided later via update.Jl{\"oauth_token\": {\"access_token\": \"ya29.a0...\", \"refresh_token\": \"1//0g...\", \"scopes\": [\"email\", \"profile\"]}}R\x14\x61uthorizationDetails\x12\x98\x02\n\napi_config\x18\x0b \x01(\x0b\x32\x17.google.protobuf.StructB\xdf\x01\x92\x41\xdb\x01\x32\x86\x01Optional JSON configuration for connector-specific API settings such as rate limits, custom API endpoints, timeouts, or feature flags.JP{\"rate_limit\": 1000, \"timeout\": 30, \"base_url\": \"https://api.custom-domain.com\"}R\tapiConfigJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\n\x10\x0b\"\xbc\x05\n\x16UpdateConnectedAccount\x12\x8d\x03\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\xa1\x02\x92\x41\x9d\x02\x32\x99\x01Updated authentication credentials. Provide new OAuth tokens (e.g., after refresh) or updated static auth details. Only included fields will be modified.J\x7f{\"oauth_token\": {\"access_token\": \"ya29.new_token...\", \"refresh_token\": \"1//0g...\", \"scopes\": [\"email\", \"profile\", \"calendar\"]}}R\x14\x61uthorizationDetails\x12\xe1\x01\n\napi_config\x18\n \x01(\x0b\x32\x17.google.protobuf.StructB\xa8\x01\x92\x41\xa4\x01\x32}Updated JSON configuration for API-specific settings. Merges with existing configuration - only provided fields are modified.J#{\"rate_limit\": 2000, \"timeout\": 60}R\tapiConfigJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n\"\xe0\x08\n\x17\x43onnectedAccountForList\x12{\n\nidentifier\x18\x01 \x01(\tB[\x92\x41X2BThe unique identifier for this account in the third-party service.J\x12\"user@example.com\"R\nidentifier\x12]\n\x08provider\x18\x02 \x01(\tBA\x92\x41>22OAuth provider name (e.g., \'google\', \'microsoft\').J\x08\"google\"R\x08provider\x12h\n\x06status\x18\x03 \x01(\x0e\x32/.scalekit.v1.connected_accounts.ConnectorStatusB\x1f\x92\x41\x1c\x32\x1a\x43urrent connection status.R\x06status\x12\x80\x01\n\x12\x61uthorization_type\x18\x04 \x01(\x0e\x32-.scalekit.v1.connected_accounts.ConnectorTypeB\"\x92\x41\x1f\x32\x1d\x41uthorization mechanism type.R\x11\x61uthorizationType\x12~\n\x10token_expires_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB8\x92\x41\x35\x32\x1bToken expiration timestamp.J\x16\"2024-12-31T23:59:59Z\"R\x0etokenExpiresAt\x12t\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB9\x92\x41\x36\x32\x1cLast modification timestamp.J\x16\"2024-03-20T15:04:05Z\"R\tupdatedAt\x12\x42\n\tconnector\x18\x08 \x01(\tB$\x92\x41!2\x15\x43onnector identifier.J\x08\"notion\"R\tconnector\x12p\n\x0clast_used_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB2\x92\x41/2\x15Last usage timestamp.J\x16\"2024-03-20T14:30:00Z\"R\nlastUsedAt\x12Q\n\x02id\x18\n \x01(\tBA\x92\x41>2$Unique connected account identifier.J\x16\"ca_24834495392086178\"R\x02id\x12w\n\rconnection_id\x18\x0b \x01(\tBR\x92\x41\x46\x32*Parent connection configuration reference.J\x18\"conn_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionIdJ\x04\x08\x05\x10\x06\"\x8f\x02\n\x14\x41uthorizationDetails\x12M\n\x0boauth_token\x18\x01 \x01(\x0b\x32*.scalekit.v1.connected_accounts.OauthTokenH\x00R\noauthToken\x12M\n\x0bstatic_auth\x18\x02 \x01(\x0b\x32*.scalekit.v1.connected_accounts.StaticAuthH\x00R\nstaticAuth\x12N\n\ngoogle_dwd\x18\x03 \x01(\x0b\x32-.scalekit.v1.connected_accounts.GoogleDWDAuthH\x00R\tgoogleDwdB\t\n\x07\x64\x65tails\"\xd8\x04\n\rGoogleDWDAuth\x12\x88\x01\n\x07subject\x18\x01 \x01(\tBn\x92\x41k2UEmail address of the Google Workspace user to impersonate via Domain-Wide Delegation.J\x12\"user@example.com\"R\x07subject\x12\x91\x01\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\tBn\x92\x41h2POAuth access token acquired via the jwt-bearer grant. Present in responses only.J\x14\"ya29.a0AfH6SMBx...\"\xe0\x41\x03R\x0b\x61\x63\x63\x65ssToken\x12\x9d\x01\n\x06scopes\x18\x03 \x03(\tB\x84\x01\x92\x41~2>OAuth scopes granted to this token. Present in responses only.J<[\"openid\", \"https://www.googleapis.com/auth/userinfo.email\"]\xe0\x41\x03R\x06scopes\x12\x87\x01\n\x10token_expires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampBA\x92\x41;29When the access token expires. Present in responses only.\xe0\x41\x03R\x0etokenExpiresAt\"\xdc\x05\n\nOauthToken\x12\xa0\x01\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\tB}\x92\x41z2bOAuth access token for API requests. Typically short-lived and must be refreshed after expiration.J\x14\"ya29.a0AfH6SMBx...\"R\x0b\x61\x63\x63\x65ssToken\x12\xae\x01\n\rrefresh_token\x18\x02 \x01(\tB\x88\x01\x92\x41\x84\x01\x32nOAuth refresh token for obtaining new access tokens. Long-lived and used to maintain persistent authorization.J\x12\"1//0gHJxZ-Lb2...\"R\x0crefreshToken\x12\xe1\x01\n\x06scopes\x18\x03 \x03(\tB\xc8\x01\x92\x41\xc4\x01\x32\\List of granted OAuth scopes defining the permissions and access levels for this connection.Jd[\"https://www.googleapis.com/auth/drive.readonly\", \"https://www.googleapis.com/auth/userinfo.email\"]R\x06scopes\x12\x95\x01\n\x06\x64omain\x18\x04 \x01(\tB}\x92\x41z2iAssociated domain for workspace or organization-scoped OAuth connections (e.g., Google Workspace domain).J\r\"example.com\"R\x06\x64omain\"\xf4\x01\n\nStaticAuth\x12\xe5\x01\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32\x17.google.protobuf.StructB\xb1\x01\x92\x41\xad\x01\x32zFlexible JSON structure containing static credentials. Format varies by connector type (API key, username/password, etc.).J/{\"api_key\": \"sk_live_...\", \"api_secret\": \"...\"}R\x07\x64\x65tails\"\x83\x02\n\x1aGetConnectedAccountRequest\x12\xe4\x01\n\x02id\x18\x01 \x01(\tB\xd3\x01\x92\x41\xc6\x01\x32\xab\x01Unique identifier for the connected account. Always prefixed with \'ca_\'. If omitted (via the /this path), the connected account is resolved from the current token context.J\x16\"ca_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x02id\"\xc5\x01\n\x1bGetConnectedAccountResponse\x12\xa5\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountBF\x92\x41\x43\x32\x41The connected account with its details and authentication status.R\x10\x63onnectedAccount\"\xb2\x01\n!DisconnectConnectedAccountRequest\x12\x8c\x01\n\x02id\x18\x01 \x01(\tB|\x92\x41p2VUnique identifier for the connected account to disconnect. Always prefixed with \'ca_\'.J\x16\"ca_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x02id\"\xc6\x01\n\"DisconnectConnectedAccountResponse\x12\x9f\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB@\x92\x41=2;The connected account with its updated DISCONNECTED status.R\x10\x63onnectedAccount*\x8b\x01\n\x0f\x43onnectorStatus\x12!\n\x1d\x43ONNECTION_STATUS_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0b\n\x07\x45XPIRED\x10\x02\x12\x10\n\x0cPENDING_AUTH\x10\x03\x12\x18\n\x14PENDING_VERIFICATION\x10\x04\x12\x10\n\x0c\x44ISCONNECTED\x10\x05*\xb3\x01\n\rConnectorType\x12\x1f\n\x1b\x43ONNECTION_TYPE_UNSPECIFIED\x10\x00\x12\t\n\x05OAUTH\x10\x01\x12\x0b\n\x07\x41PI_KEY\x10\x02\x12\x0e\n\nBASIC_AUTH\x10\x03\x12\x10\n\x0c\x42\x45\x41RER_TOKEN\x10\x04\x12\n\n\x06\x43USTOM\x10\x05\x12\t\n\x05\x42\x41SIC\x10\x06\x12\r\n\tOAUTH_M2M\x10\x07\x12\x11\n\rTRELLO_OAUTH1\x10\x08\x12\x0e\n\nGOOGLE_DWD\x10\t2\xa0O\n\x17\x43onnectedAccountService\x12\xde\x06\n\x15ListConnectedAccounts\x12<.scalekit.v1.connected_accounts.ListConnectedAccountsRequest\x1a=.scalekit.v1.connected_accounts.ListConnectedAccountsResponse\"\xc7\x05\x92\x41\x9b\x05\n\x12\x43onnected Accounts\x12\x17List connected accounts\x1a\x9a\x02Retrieves a paginated list of connected accounts for third-party integrations. Filter by organization, user, connector type, provider, or identifier. Returns OAuth tokens, API keys, and connection status for each account. Use pagination tokens to navigate through large result sets.J\xaf\x01\n\x03\x32\x30\x30\x12\xa7\x01\nbSuccessfully retrieved the list of connected accounts with their authentication details and status\x12\x41\n?\x1a=.scalekit.v1.connected_accounts.ListConnectedAccountsResponseJY\n\x03\x34\x30\x30\x12R\nPInvalid request - occurs when query parameters are malformed or validation failsJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/v1/connected_accounts\x12\xe0\x06\n\x17SearchConnectedAccounts\x12>.scalekit.v1.connected_accounts.SearchConnectedAccountsRequest\x1a?.scalekit.v1.connected_accounts.SearchConnectedAccountsResponse\"\xc3\x05\x92\x41\x90\x05\n\x12\x43onnected Accounts\x12\x19Search connected accounts\x1a\x99\x02Search for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors. The search performs case-insensitive matching across account details. Returns paginated results with account status and authentication type information.J\x99\x01\n\x03\x32\x30\x30\x12\x91\x01\nJSuccessfully retrieved matching connected accounts with pagination support\x12\x43\nA\x1a?.scalekit.v1.connected_accounts.SearchConnectedAccountsResponseJc\n\x03\x34\x30\x30\x12\\\nZInvalid request - query parameter is too short (minimum 3 characters) or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02#\x12!/api/v1/connected_accounts:search\x12\xfe\x07\n\x16\x43reateConnectedAccount\x12=.scalekit.v1.connected_accounts.CreateConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.CreateConnectedAccountResponse\"\xe4\x06\x92\x41\xb5\x06\n\x12\x43onnected Accounts\x12\x1a\x43reate a connected account\x1a\xdf\x02\x43reates a new connected account with OAuth tokens or API credentials for third-party service integration. Supply authorization details including access tokens, refresh tokens, scopes, and optional API configuration. The account can be scoped to an organization or user. Returns the created account with its unique identifier and authentication status.J\xa4\x01\n\x03\x32\x30\x31\x12\x9c\x01\nVConnected account created successfully with authentication credentials stored securely\x12\x42\n@\x1a>.scalekit.v1.connected_accounts.CreateConnectedAccountResponseJg\n\x03\x34\x30\x30\x12`\n^Invalid request - missing required fields, invalid authorization details, or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJM\n\x03\x34\x30\x39\x12\x46\nDConflict - connected account with the same identifier already exists\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1f\"\x1a/api/v1/connected_accounts:\x01*\x12\xf0\x07\n\x16UpdateConnectedAccount\x12=.scalekit.v1.connected_accounts.UpdateConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.UpdateConnectedAccountResponse\"\xd6\x06\x92\x41\xa6\x06\n\x12\x43onnected Accounts\x12$Update connected account credentials\x1a\xd2\x02Updates authentication credentials and configuration for an existing connected account. Modify OAuth tokens, refresh tokens, access scopes, or API configuration settings. Specify the account by ID, or by combination of organization/user, connector, and identifier. Returns the updated account with new token expiry and status information.J\x9a\x01\n\x03\x32\x30\x30\x12\x92\x01\nLConnected account updated successfully with new credentials or configuration\x12\x42\n@\x1a>.scalekit.v1.connected_accounts.UpdateConnectedAccountResponseJg\n\x03\x34\x30\x30\x12`\n^Invalid request - missing required fields, invalid authorization details, or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJK\n\x03\x34\x30\x34\x12\x44\nBConnected account not found - the specified account does not exist\x82\xb5\x18\x03\x18\xc4\x01\x82\xd3\xe4\x93\x02\x1f\x1a\x1a/api/v1/connected_accounts:\x01*\x12\xc6\x06\n\x16\x44\x65leteConnectedAccount\x12=.scalekit.v1.connected_accounts.DeleteConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.DeleteConnectedAccountResponse\"\xac\x05\x92\x41\xf6\x04\n\x12\x43onnected Accounts\x12\x1a\x44\x65lete a connected account\x1a\x9f\x02Permanently removes a connected account and revokes all associated authentication credentials. Identify the account by ID, or by combination of organization/user, connector, and identifier. This action cannot be undone. All OAuth tokens and API keys for this account will be invalidated.JK\n\x03\x32\x30\x30\x12\x44\nBConnected account deleted successfully and all credentials revokedJD\n\x03\x34\x30\x30\x12=\n;Invalid request - malformed parameters or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJK\n\x03\x34\x30\x34\x12\x44\nBConnected account not found - the specified account does not exist\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02&\"!/api/v1/connected_accounts:delete:\x01*\x12\xff\x06\n\x1fGetMagicLinkForConnectedAccount\x12\x46.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountRequest\x1aG.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountResponse\"\xca\x05\x92\x41\x90\x05\n\x12\x43onnected Accounts\x12\"Generate authentication magic link\x1a\xa2\x02\x43reates a time-limited magic link for connecting or re-authorizing a third-party account. The link directs users to the OAuth authorization flow for the specified connector. Returns the generated link URL and expiration timestamp. Links typically expire after a short duration for security.J\x9f\x01\n\x03\x32\x30\x30\x12\x97\x01\nHMagic link generated successfully with authorization URL and expiry time\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountResponseJK\n\x03\x34\x30\x30\x12\x44\nBInvalid request - missing required parameters or invalid connectorJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02*\"%/api/v1/connected_accounts/magic_link:\x01*\x12\x85\x06\n\x13GetConnectedAccount\x12:.scalekit.v1.connected_accounts.GetConnectedAccountRequest\x1a;.scalekit.v1.connected_accounts.GetConnectedAccountResponse\"\xf4\x04\x92\x41\x90\x04\n\x12\x43onnected Accounts\x12\x17Get a connected account\x1a\xb8\x01Retrieves a connected account by its unique ID. Use the path \'/this\' (e.g. /api/v1/connected_accounts/this) to retrieve the connected account associated with the current token context.Jv\n\x03\x32\x30\x30\x12o\n,Successfully retrieved the connected account\x12?\n=\x1a;.scalekit.v1.connected_accounts.GetConnectedAccountResponseJD\n\x03\x34\x30\x30\x12=\n;Invalid request - missing or malformed connected account IDJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJ$\n\x03\x34\x30\x34\x12\x1d\n\x1b\x43onnected account not found\x82\xb5\x18\x03\x18\xc4\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x44\x12\x1f/api/v1/connected_accounts/thisZ!\x12\x1f/api/v1/connected_accounts/{id}\x12\x95\x06\n\x1a\x44isconnectConnectedAccount\x12\x41.scalekit.v1.connected_accounts.DisconnectConnectedAccountRequest\x1a\x42.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponse\"\xef\x04\x92\x41\xf2\x03\n\x12\x43onnected Accounts\x12\x1e\x44isconnect a connected account\x1a\x88\x01\x44isconnects a connected account by setting its status to DISCONNECTED. The account record is retained but is marked as no longer active.J\x80\x01\n\x03\x32\x30\x30\x12y\n/Successfully disconnected the connected account\x12\x46\nD\x1a\x42.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponseJD\n\x03\x34\x30\x30\x12=\n;Invalid request - missing or malformed connected account IDJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJ$\n\x03\x34\x30\x34\x12\x1d\n\x1b\x43onnected account not found\x82\xb5\x18\x03\x18\xc4\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02]\"*/api/v1/connected_accounts/{id}:disconnect:\x01*Z,\"\'/api/v1/connected_accounts/-:disconnect:\x01*\x12\xbf\x07\n\x17GetConnectedAccountAuth\x12\x46.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierRequest\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponse\"\x92\x06\x92\x41\xe1\x05\n\x12\x43onnected Accounts\x12&Get connected account auth credentials\x1a\xab\x02Retrieves complete authentication details for a connected account including OAuth tokens, refresh tokens, scopes, and API configuration. Query by account ID or by combination of organization/user, connector, and identifier. Returns sensitive credential information - use appropriate access controls.J\xa0\x01\n\x03\x32\x30\x30\x12\x98\x01\nISuccessfully retrieved connected account with full authentication details\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\x03\x34\x30\x30\x12\x35\n3Invalid request - missing required query parametersJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJP\n\x03\x34\x30\x34\x12I\nGConnected account not found - no account matches the specified criteria\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/connected_accounts/auth\x12\xfb\x06\n\x1aGetConnectedAccountDetails\x12\x46.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierRequest\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponse\"\xcb\x05\x92\x41\x97\x05\n\x12\x43onnected Accounts\x12\x1eGet connected account metadata\x1a\x83\x02Returns metadata for a connected account including status, connector type, provider, and configuration without exposing stored authorization credentials. Look up by account ID, or by a combination of organization (or user), connector, and external identifier.J\x86\x01\n\x03\x32\x30\x30\x12\x7f\n0Successfully retrieved connected account details\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\x03\x34\x30\x30\x12\x35\n3Invalid request - missing required query parametersJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJP\n\x03\x34\x30\x34\x12I\nGConnected account not found - no account matches the specified criteria\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02$\x12\"/api/v1/connected_accounts/details\x12\xbb\x07\n\x1aVerifyConnectedAccountUser\x12\x41.scalekit.v1.connected_accounts.VerifyConnectedAccountUserRequest\x1a\x42.scalekit.v1.connected_accounts.VerifyConnectedAccountUserResponse\"\x95\x06\x92\x41\xda\x05\n\x12\x43onnected Accounts\x12\x1dVerify connected account user\x1a\xa4\x02\x43onfirms the user assertion and activates the connected account after the user completes third-party OAuth. Called by the B2B app server with auth_request_id and identifier. Validates that the asserted identifier matches the one stored on the auth request and promotes pending tokens to live.J\x8a\x01\n\x03\x32\x30\x30\x12\x82\x01\n8Verification successful; connected account is now ACTIVE\x12\x46\nD\x1a\x42.scalekit.v1.connected_accounts.VerifyConnectedAccountUserResponseJ6\n\x03\x34\x30\x30\x12/\n-Invalid request - missing or malformed fieldsJ7\n\x03\x34\x30\x31\x12\x30\n.Unauthorized - invalid or missing access tokenJ(\n\x03\x34\x30\x33\x12!\n\x1f\x46orbidden - identifier mismatchJV\n\x03\x34\x30\x34\x12O\nMNot found - no pending flow for the given auth_request_id or already consumed\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02+\"&/api/v1/connected_accounts/user/verify:\x01*\x1a\xe3\x01\x92\x41\xdf\x01\n\x12\x43onnected Accounts\x12\xc8\x01Manage connected accounts for third-party integrations and OAuth connections. Connected accounts represent authenticated access to external services like Google, Notion, Slack, and other applications.B\xa4\x02Z 0)B\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifier\"\xbb\x06\n\x1dListConnectedAccountsResponse\x12\xdc\x01\n\x12\x63onnected_accounts\x18\x01 \x03(\x0b\x32\x37.scalekit.v1.connected_accounts.ConnectedAccountForListBt\x92\x41q2oList of connected accounts matching the filter criteria. Excludes sensitive authorization details for security.R\x11\x63onnectedAccounts\x12\x99\x01\n\ntotal_size\x18\x02 \x01(\rBz\x92\x41w2pTotal count of connected accounts matching the filter criteria across all pages. Use for calculating pagination.J\x03\x31\x30\x30R\ttotalSize\x12\xd2\x01\n\x0fnext_page_token\x18\x03 \x01(\tB\xa9\x01\x92\x41\x9c\x01\x32\x81\x01Pagination token for retrieving the next page. Empty if this is the last page. Pass this value to page_token in the next request.J\x16\"eyJvZmZzZXQiOjIwfQ==\"\xbaH\x06r\x04\x10\x00\x18 R\rnextPageToken\x12\xc9\x01\n\x0fprev_page_token\x18\x04 \x01(\tB\xa0\x01\x92\x41\x93\x01\x32}Pagination token for retrieving the previous page. Empty if this is the first page. Pass this value to page_token to go back.J\x12\"eyJvZmZzZXQiOjB9\"\xbaH\x06r\x04\x10\x00\x18 R\rprevPageToken\"\xe0\x06\n\x1eSearchConnectedAccountsRequest\x12\xb9\x01\n\x05query\x18\x01 \x01(\tB\xa2\x01\x92\x41\x91\x01\x32\x86\x01Search term to match against connected account identifiers, providers, or connectors. Must be at least 3 characters. Case insensitive.J\x06google\xbaH\nr\x05\x10\x03\x18\xc8\x01\xc8\x01\x01R\x05query\x12\x85\x01\n\tpage_size\x18\x02 \x01(\rBh\x92\x41^2XMaximum number of connected accounts to return per page. Value must be between 1 and 30.J\x02\x33\x30\xbaH\x04*\x02\x18\x1eR\x08pageSize\x12\xa5\x01\n\npage_token\x18\x03 \x01(\tB\x85\x01\x92\x41\x81\x01\x32\x61Token from a previous response for pagination. Provide this to retrieve the next page of results.J\x1c\x65yJwYWdlIjoyLCJsaW1pdCI6MzB9R\tpageToken\x12i\n\rconnection_id\x18\x04 \x01(\tBD\x92\x41\x38\x32*Connection ID to filter connected accountsJ\n\"conn_123\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionId:\xe6\x01\x92\x41\xe2\x01\n\x9c\x01*\x19Search Connected Accounts2\x7fSearch for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors2Aquery=google&page_size=30&page_token=eyJwYWdlIjoyLCJsaW1pdCI6MzB9\"\x87\x05\n\x1fSearchConnectedAccountsResponse\x12\xcc\x01\n\x12\x63onnected_accounts\x18\x01 \x03(\x0b\x32\x37.scalekit.v1.connected_accounts.ConnectedAccountForListBd\x92\x41\x61\x32_List of connected accounts matching the search query. Excludes sensitive authorization details.R\x11\x63onnectedAccounts\x12l\n\ntotal_size\x18\x02 \x01(\rBM\x92\x41J2CTotal count of accounts matching the search query across all pages.J\x03\x31\x30\x30R\ttotalSize\x12\x91\x01\n\x0fnext_page_token\x18\x03 \x01(\tBi\x92\x41]2CPagination token for the next page. Empty if this is the last page.J\x16\"eyJvZmZzZXQiOjMwfQ==\"\xbaH\x06r\x04\x10\x00\x18 R\rnextPageToken\x12\x92\x01\n\x0fprev_page_token\x18\x04 \x01(\tBj\x92\x41^2HPagination token for the previous page. Empty if this is the first page.J\x12\"eyJvZmZzZXQiOjB9\"\xbaH\x06r\x04\x10\x00\x18 R\rprevPageToken\"\xa0\x08\n\x1d\x43reateConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12\xbd\x02\n\x11\x63onnected_account\x18\x05 \x01(\x0b\x32\x36.scalekit.v1.connected_accounts.CreateConnectedAccountB\xd7\x01\x92\x41\xcd\x01\x32*Details of the connected account to createJ\x9e\x01{ \"authorization_type\": \"OAUTH2\", \"authorization_details\": { \"oauth_token\": { \"access_token\": \"...\", \"refresh_token\": \"...\", \"scopes\": [\"read\", \"write\"] } } }\xbaH\x03\xc8\x01\x01R\x10\x63onnectedAccountB\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifier\"\x8d\x02\n\x1e\x43reateConnectedAccountResponse\x12\xea\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB\x8a\x01\x92\x41\x86\x01\x32\x83\x01The newly created connected account with its unique identifier, status, and complete authorization details including access tokens.R\x10\x63onnectedAccount\"\x90\t\n\x1dUpdateConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12g\n\x02id\x18\x06 \x01(\tBR\x92\x41\x41\x32\x35Unique identifier for the connected account to updateJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x12\xbd\x02\n\x11\x63onnected_account\x18\x05 \x01(\x0b\x32\x36.scalekit.v1.connected_accounts.UpdateConnectedAccountB\xd7\x01\x92\x41\xcd\x01\x32*Details of the connected account to updateJ\x9e\x01{ \"authorization_type\": \"OAUTH2\", \"authorization_details\": { \"oauth_token\": { \"access_token\": \"...\", \"refresh_token\": \"...\", \"scopes\": [\"read\", \"write\"] } } }\xbaH\x03\xc8\x01\x01R\x10\x63onnectedAccountB\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\"\xf7\x01\n\x1eUpdateConnectedAccountResponse\x12\xd4\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountBu\x92\x41r2pThe updated connected account with refreshed credentials, new token expiry, and modified configuration settings.R\x10\x63onnectedAccount\"\xd0\x06\n\x1d\x44\x65leteConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12g\n\x02id\x18\x05 \x01(\tBR\x92\x41\x41\x32\x35Unique identifier for the connected account to deleteJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\" \n\x1e\x44\x65leteConnectedAccountResponse\"\xdf\t\n&GetMagicLinkForConnectedAccountRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12]\n\x02id\x18\x05 \x01(\tBH\x92\x41\x37\x32+Unique identifier for the connected accountJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x12\xcf\x01\n\x05state\x18\x07 \x01(\tB\xb3\x01\x92\x41\xa5\x01\x32wOptional opaque state value. State added to the user verify redirect URL query params to validate the user verificationJ*\"QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=\"\xbaH\x07r\x05\x10\x00\x18\x80\x04H\x05R\x05state\x88\x01\x01\x12\x9d\x01\n\x0fuser_verify_url\x18\x08 \x01(\tBp\x92\x41T2\"B2B app\'s user verify redirect URLJ.\"https://app.yourapp.com/user/verify/callback\"\xbaH\x16r\x14\x10\x00\x18\x80\x10\x32\r^$|^https?://H\x06R\ruserVerifyUrl\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_idB\x08\n\x06_stateB\x12\n\x10_user_verify_url\"\x9c\x02\n\'GetMagicLinkForConnectedAccountResponse\x12r\n\x04link\x18\x01 \x01(\tB^\x92\x41[2%Authentication link for the connectorJ2\"https://notion.com/oauth/authorize?client_id=...\"R\x04link\x12}\n\x06\x65xpiry\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampBI\x92\x41\x46\x32,Expiry timestamp for the authentication linkJ\x16\"2024-03-20T15:04:05Z\"R\x06\x65xpiry\"\xeb\x02\n!VerifyConnectedAccountUserRequest\x12\xc8\x01\n\x0f\x61uth_request_id\x18\x01 \x01(\tB\x9f\x01\x92\x41\x8e\x01\x32`Auth request ID as base64url-encoded opaque token from the user verify redirect URL query paramsJ*\"QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=\"\xe0\x41\x02\xbaH\x07r\x05\x10\x01\x18\xe8\x07R\rauthRequestId\x12{\n\nidentifier\x18\x02 \x01(\tB[\x92\x41K25Current logged in user\'s connected account identifierJ\x12\"user@example.com\"\xe0\x41\x02\xbaH\x07r\x05\x10\x01\x18\xc8\x01R\nidentifier\"\xd3\x01\n\"VerifyConnectedAccountUserResponse\x12\xac\x01\n\x1dpost_user_verify_redirect_url\x18\x01 \x01(\tBj\x92\x41g29URL to redirect the user to after successful verificationJ*\"https://env1.example.com/connect/success\"R\x19postUserVerifyRedirectUrl\"\xcf\x06\n&GetConnectedAccountByIdentifierRequest\x12t\n\x0forganization_id\x18\x01 \x01(\tBF\x92\x41:2!Organization ID for the connectorJ\x15\"org_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x00R\x0eorganizationId\x88\x01\x01\x12]\n\x07user_id\x18\x02 \x01(\tB?\x92\x41\x33\x32\x19User ID for the connectorJ\x16\"user_121312434123312\"\xbaH\x06r\x04\x10\x00\x18 H\x01R\x06userId\x88\x01\x01\x12\xdb\x01\n\tconnector\x18\x03 \x01(\tB\xb7\x01\x92\x41\x95\x01\x32\x88\x01\x43onnector identifier (e.g., \'notion\', \'slack\', \'google\'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed.J\x08\"notion\"\xbaH\x1br\x19\x10\x00\x18\x90\x03\x32\x12^[a-zA-Z0-9_: -]*$H\x02R\tconnector\x88\x01\x01\x12\xce\x01\n\nidentifier\x18\x04 \x01(\tB\xa8\x01\x92\x41\x9b\x01\x32\x84\x01The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).J\x12\"user@example.com\"\xbaH\x06r\x04\x10\x00\x18\x64H\x03R\nidentifier\x88\x01\x01\x12]\n\x02id\x18\x05 \x01(\tBH\x92\x41\x37\x32+Unique identifier for the connected accountJ\x08\"ca_123\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_H\x04R\x02id\x88\x01\x01\x42\x12\n\x10_organization_idB\n\n\x08_user_idB\x0c\n\n_connectorB\r\n\x0b_identifierB\x05\n\x03_id\"\xbe\x02\n\'GetConnectedAccountByIdentifierResponse\x12\x92\x02\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB\xb2\x01\x92\x41\xae\x01\x32\xab\x01The connected account with complete details including sensitive authorization credentials (access tokens, refresh tokens, scopes). Handle with appropriate access controls.R\x10\x63onnectedAccount\"\xe3\x13\n\x10\x43onnectedAccount\x12\xbc\x01\n\nidentifier\x18\x01 \x01(\tB\x9b\x01\x92\x41\x97\x01\x32\x80\x01The unique identifier for this account in the third-party service. Typically an email address, user ID, or workspace identifier.J\x12\"user@example.com\"R\nidentifier\x12\xaa\x01\n\x08provider\x18\x02 \x01(\tB\x8d\x01\x92\x41\x89\x01\x32}OAuth provider name (e.g., \'google\', \'microsoft\', \'github\'). Identifies which authentication service manages this connection.J\x08\"google\"R\x08provider\x12\xe4\x01\n\x06status\x18\x03 \x01(\x0e\x32/.scalekit.v1.connected_accounts.ConnectorStatusB\x9a\x01\x92\x41\x96\x01\x32\x93\x01\x43urrent status of the connected account. Indicates if the account is active, expired, pending authorization, or pending user identity verification.R\x06status\x12\xe9\x01\n\x12\x61uthorization_type\x18\x04 \x01(\x0e\x32-.scalekit.v1.connected_accounts.ConnectorTypeB\x8a\x01\x92\x41\x86\x01\x32\x83\x01Type of authorization mechanism used. Specifies whether this connection uses OAuth, API keys, bearer tokens, or other auth methods.R\x11\x61uthorizationType\x12\x81\x02\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\x95\x01\x92\x41\x91\x01\x32\x8e\x01Sensitive authentication credentials including access tokens, refresh tokens, and scopes. Contains either OAuth tokens or static auth details.R\x14\x61uthorizationDetails\x12\xce\x01\n\x10token_expires_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x87\x01\x92\x41\x83\x01\x32iExpiration timestamp for the access token. After this time, the token must be refreshed or re-authorized.J\x16\"2024-12-31T23:59:59Z\"R\x0etokenExpiresAt\x12\xc9\x01\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x8d\x01\x92\x41\x89\x01\x32oTimestamp when this connected account was last modified. Updated whenever credentials or configuration changes.J\x16\"2024-03-20T15:04:05Z\"R\tupdatedAt\x12\xae\x01\n\tconnector\x18\x08 \x01(\tB\x8f\x01\x92\x41\x8b\x01\x32\x7f\x43onnector identifier (e.g., \'notion\', \'slack\', \'salesforce\'). Indicates which third-party application this account connects to.J\x08\"notion\"R\tconnector\x12\xcd\x01\n\x0clast_used_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x8e\x01\x92\x41\x8a\x01\x32pTimestamp when this connected account was last used to make an API call. Useful for tracking active connections.J\x16\"2024-03-20T14:30:00Z\"R\nlastUsedAt\x12\x98\x01\n\x02id\x18\n \x01(\tB\x87\x01\x92\x41v2\\Unique Scalekit-generated identifier for this connected account. Always prefixed with \'ca_\'.J\x16\"ca_24834495392086178\"\xbaH\x0br\t\x10\x00\x18 :\x03\x63\x61_R\x02id\x12\xc6\x01\n\rconnection_id\x18\x0b \x01(\tB\xa0\x01\x92\x41\x93\x01\x32wReference to the parent connection configuration. Links this account to a specific connector setup in your environment.J\x18\"conn_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionId\x12\x89\x02\n\napi_config\x18\x0c \x01(\x0b\x32\x17.google.protobuf.StructB\xd0\x01\x92\x41\xcc\x01\x32xOptional JSON configuration for connector-specific API settings such as rate limits, custom endpoints, or feature flags.JP{\"rate_limit\": 1000, \"timeout\": 30, \"base_url\": \"https://api.custom-domain.com\"}R\tapiConfig\"\x9a\x06\n\x16\x43reateConnectedAccount\x12\xae\x03\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\xc2\x02\x92\x41\xbe\x02\x32\xcd\x01Optional authentication credentials for the connected account. Include OAuth tokens (access_token, refresh_token, scopes) or static auth details (API keys, bearer tokens). Can be provided later via update.Jl{\"oauth_token\": {\"access_token\": \"ya29.a0...\", \"refresh_token\": \"1//0g...\", \"scopes\": [\"email\", \"profile\"]}}R\x14\x61uthorizationDetails\x12\x98\x02\n\napi_config\x18\x0b \x01(\x0b\x32\x17.google.protobuf.StructB\xdf\x01\x92\x41\xdb\x01\x32\x86\x01Optional JSON configuration for connector-specific API settings such as rate limits, custom API endpoints, timeouts, or feature flags.JP{\"rate_limit\": 1000, \"timeout\": 30, \"base_url\": \"https://api.custom-domain.com\"}R\tapiConfigJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\n\x10\x0b\"\xbc\x05\n\x16UpdateConnectedAccount\x12\x8d\x03\n\x15\x61uthorization_details\x18\x05 \x01(\x0b\x32\x34.scalekit.v1.connected_accounts.AuthorizationDetailsB\xa1\x02\x92\x41\x9d\x02\x32\x99\x01Updated authentication credentials. Provide new OAuth tokens (e.g., after refresh) or updated static auth details. Only included fields will be modified.J\x7f{\"oauth_token\": {\"access_token\": \"ya29.new_token...\", \"refresh_token\": \"1//0g...\", \"scopes\": [\"email\", \"profile\", \"calendar\"]}}R\x14\x61uthorizationDetails\x12\xe1\x01\n\napi_config\x18\n \x01(\x0b\x32\x17.google.protobuf.StructB\xa8\x01\x92\x41\xa4\x01\x32}Updated JSON configuration for API-specific settings. Merges with existing configuration - only provided fields are modified.J#{\"rate_limit\": 2000, \"timeout\": 60}R\tapiConfigJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n\"\xe0\x08\n\x17\x43onnectedAccountForList\x12{\n\nidentifier\x18\x01 \x01(\tB[\x92\x41X2BThe unique identifier for this account in the third-party service.J\x12\"user@example.com\"R\nidentifier\x12]\n\x08provider\x18\x02 \x01(\tBA\x92\x41>22OAuth provider name (e.g., \'google\', \'microsoft\').J\x08\"google\"R\x08provider\x12h\n\x06status\x18\x03 \x01(\x0e\x32/.scalekit.v1.connected_accounts.ConnectorStatusB\x1f\x92\x41\x1c\x32\x1a\x43urrent connection status.R\x06status\x12\x80\x01\n\x12\x61uthorization_type\x18\x04 \x01(\x0e\x32-.scalekit.v1.connected_accounts.ConnectorTypeB\"\x92\x41\x1f\x32\x1d\x41uthorization mechanism type.R\x11\x61uthorizationType\x12~\n\x10token_expires_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB8\x92\x41\x35\x32\x1bToken expiration timestamp.J\x16\"2024-12-31T23:59:59Z\"R\x0etokenExpiresAt\x12t\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB9\x92\x41\x36\x32\x1cLast modification timestamp.J\x16\"2024-03-20T15:04:05Z\"R\tupdatedAt\x12\x42\n\tconnector\x18\x08 \x01(\tB$\x92\x41!2\x15\x43onnector identifier.J\x08\"notion\"R\tconnector\x12p\n\x0clast_used_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampB2\x92\x41/2\x15Last usage timestamp.J\x16\"2024-03-20T14:30:00Z\"R\nlastUsedAt\x12Q\n\x02id\x18\n \x01(\tBA\x92\x41>2$Unique connected account identifier.J\x16\"ca_24834495392086178\"R\x02id\x12w\n\rconnection_id\x18\x0b \x01(\tBR\x92\x41\x46\x32*Parent connection configuration reference.J\x18\"conn_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x0c\x63onnectionIdJ\x04\x08\x05\x10\x06\"\x8f\x02\n\x14\x41uthorizationDetails\x12M\n\x0boauth_token\x18\x01 \x01(\x0b\x32*.scalekit.v1.connected_accounts.OauthTokenH\x00R\noauthToken\x12M\n\x0bstatic_auth\x18\x02 \x01(\x0b\x32*.scalekit.v1.connected_accounts.StaticAuthH\x00R\nstaticAuth\x12N\n\ngoogle_dwd\x18\x03 \x01(\x0b\x32-.scalekit.v1.connected_accounts.GoogleDWDAuthH\x00R\tgoogleDwdB\t\n\x07\x64\x65tails\"\xd8\x04\n\rGoogleDWDAuth\x12\x88\x01\n\x07subject\x18\x01 \x01(\tBn\x92\x41k2UEmail address of the Google Workspace user to impersonate via Domain-Wide Delegation.J\x12\"user@example.com\"R\x07subject\x12\x91\x01\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\tBn\x92\x41h2POAuth access token acquired via the jwt-bearer grant. Present in responses only.J\x14\"ya29.a0AfH6SMBx...\"\xe0\x41\x03R\x0b\x61\x63\x63\x65ssToken\x12\x9d\x01\n\x06scopes\x18\x03 \x03(\tB\x84\x01\x92\x41~2>OAuth scopes granted to this token. Present in responses only.J<[\"openid\", \"https://www.googleapis.com/auth/userinfo.email\"]\xe0\x41\x03R\x06scopes\x12\x87\x01\n\x10token_expires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampBA\x92\x41;29When the access token expires. Present in responses only.\xe0\x41\x03R\x0etokenExpiresAt\"\xdc\x05\n\nOauthToken\x12\xa0\x01\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\tB}\x92\x41z2bOAuth access token for API requests. Typically short-lived and must be refreshed after expiration.J\x14\"ya29.a0AfH6SMBx...\"R\x0b\x61\x63\x63\x65ssToken\x12\xae\x01\n\rrefresh_token\x18\x02 \x01(\tB\x88\x01\x92\x41\x84\x01\x32nOAuth refresh token for obtaining new access tokens. Long-lived and used to maintain persistent authorization.J\x12\"1//0gHJxZ-Lb2...\"R\x0crefreshToken\x12\xe1\x01\n\x06scopes\x18\x03 \x03(\tB\xc8\x01\x92\x41\xc4\x01\x32\\List of granted OAuth scopes defining the permissions and access levels for this connection.Jd[\"https://www.googleapis.com/auth/drive.readonly\", \"https://www.googleapis.com/auth/userinfo.email\"]R\x06scopes\x12\x95\x01\n\x06\x64omain\x18\x04 \x01(\tB}\x92\x41z2iAssociated domain for workspace or organization-scoped OAuth connections (e.g., Google Workspace domain).J\r\"example.com\"R\x06\x64omain\"\xf4\x01\n\nStaticAuth\x12\xe5\x01\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32\x17.google.protobuf.StructB\xb1\x01\x92\x41\xad\x01\x32zFlexible JSON structure containing static credentials. Format varies by connector type (API key, username/password, etc.).J/{\"api_key\": \"sk_live_...\", \"api_secret\": \"...\"}R\x07\x64\x65tails\"\x83\x02\n\x1aGetConnectedAccountRequest\x12\xe4\x01\n\x02id\x18\x01 \x01(\tB\xd3\x01\x92\x41\xc6\x01\x32\xab\x01Unique identifier for the connected account. Always prefixed with \'ca_\'. If omitted (via the /this path), the connected account is resolved from the current token context.J\x16\"ca_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x02id\"\xc5\x01\n\x1bGetConnectedAccountResponse\x12\xa5\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountBF\x92\x41\x43\x32\x41The connected account with its details and authentication status.R\x10\x63onnectedAccount\"\xb2\x01\n!DisconnectConnectedAccountRequest\x12\x8c\x01\n\x02id\x18\x01 \x01(\tB|\x92\x41p2VUnique identifier for the connected account to disconnect. Always prefixed with \'ca_\'.J\x16\"ca_24834495392086178\"\xbaH\x06r\x04\x10\x00\x18 R\x02id\"\xc6\x01\n\"DisconnectConnectedAccountResponse\x12\x9f\x01\n\x11\x63onnected_account\x18\x01 \x01(\x0b\x32\x30.scalekit.v1.connected_accounts.ConnectedAccountB@\x92\x41=2;The connected account with its updated DISCONNECTED status.R\x10\x63onnectedAccount\"\x17\n\x15GetRedirectUrlRequest\"\xb9\x01\n\x16GetRedirectUrlResponse\x12\x9e\x01\n\x0credirect_url\x18\x01 \x01(\tB{\x92\x41x2AThe URL to redirect the user to in the connected accounts portal.J3\"https://app.example.com/portal/connected-accounts\"R\x0bredirectUrl*\x8b\x01\n\x0f\x43onnectorStatus\x12!\n\x1d\x43ONNECTION_STATUS_UNSPECIFIED\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\x0b\n\x07\x45XPIRED\x10\x02\x12\x10\n\x0cPENDING_AUTH\x10\x03\x12\x18\n\x14PENDING_VERIFICATION\x10\x04\x12\x10\n\x0c\x44ISCONNECTED\x10\x05*\xb3\x01\n\rConnectorType\x12\x1f\n\x1b\x43ONNECTION_TYPE_UNSPECIFIED\x10\x00\x12\t\n\x05OAUTH\x10\x01\x12\x0b\n\x07\x41PI_KEY\x10\x02\x12\x0e\n\nBASIC_AUTH\x10\x03\x12\x10\n\x0c\x42\x45\x41RER_TOKEN\x10\x04\x12\n\n\x06\x43USTOM\x10\x05\x12\t\n\x05\x42\x41SIC\x10\x06\x12\r\n\tOAUTH_M2M\x10\x07\x12\x11\n\rTRELLO_OAUTH1\x10\x08\x12\x0e\n\nGOOGLE_DWD\x10\t2\x93W\n\x17\x43onnectedAccountService\x12\xde\x06\n\x15ListConnectedAccounts\x12<.scalekit.v1.connected_accounts.ListConnectedAccountsRequest\x1a=.scalekit.v1.connected_accounts.ListConnectedAccountsResponse\"\xc7\x05\x92\x41\x9b\x05\n\x12\x43onnected Accounts\x12\x17List connected accounts\x1a\x9a\x02Retrieves a paginated list of connected accounts for third-party integrations. Filter by organization, user, connector type, provider, or identifier. Returns OAuth tokens, API keys, and connection status for each account. Use pagination tokens to navigate through large result sets.J\xaf\x01\n\x03\x32\x30\x30\x12\xa7\x01\nbSuccessfully retrieved the list of connected accounts with their authentication details and status\x12\x41\n?\x1a=.scalekit.v1.connected_accounts.ListConnectedAccountsResponseJY\n\x03\x34\x30\x30\x12R\nPInvalid request - occurs when query parameters are malformed or validation failsJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1c\x12\x1a/api/v1/connected_accounts\x12\xe0\x06\n\x17SearchConnectedAccounts\x12>.scalekit.v1.connected_accounts.SearchConnectedAccountsRequest\x1a?.scalekit.v1.connected_accounts.SearchConnectedAccountsResponse\"\xc3\x05\x92\x41\x90\x05\n\x12\x43onnected Accounts\x12\x19Search connected accounts\x1a\x99\x02Search for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors. The search performs case-insensitive matching across account details. Returns paginated results with account status and authentication type information.J\x99\x01\n\x03\x32\x30\x30\x12\x91\x01\nJSuccessfully retrieved matching connected accounts with pagination support\x12\x43\nA\x1a?.scalekit.v1.connected_accounts.SearchConnectedAccountsResponseJc\n\x03\x34\x30\x30\x12\\\nZInvalid request - query parameter is too short (minimum 3 characters) or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02#\x12!/api/v1/connected_accounts:search\x12\xfe\x07\n\x16\x43reateConnectedAccount\x12=.scalekit.v1.connected_accounts.CreateConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.CreateConnectedAccountResponse\"\xe4\x06\x92\x41\xb5\x06\n\x12\x43onnected Accounts\x12\x1a\x43reate a connected account\x1a\xdf\x02\x43reates a new connected account with OAuth tokens or API credentials for third-party service integration. Supply authorization details including access tokens, refresh tokens, scopes, and optional API configuration. The account can be scoped to an organization or user. Returns the created account with its unique identifier and authentication status.J\xa4\x01\n\x03\x32\x30\x31\x12\x9c\x01\nVConnected account created successfully with authentication credentials stored securely\x12\x42\n@\x1a>.scalekit.v1.connected_accounts.CreateConnectedAccountResponseJg\n\x03\x34\x30\x30\x12`\n^Invalid request - missing required fields, invalid authorization details, or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJM\n\x03\x34\x30\x39\x12\x46\nDConflict - connected account with the same identifier already exists\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1f\"\x1a/api/v1/connected_accounts:\x01*\x12\xf0\x07\n\x16UpdateConnectedAccount\x12=.scalekit.v1.connected_accounts.UpdateConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.UpdateConnectedAccountResponse\"\xd6\x06\x92\x41\xa6\x06\n\x12\x43onnected Accounts\x12$Update connected account credentials\x1a\xd2\x02Updates authentication credentials and configuration for an existing connected account. Modify OAuth tokens, refresh tokens, access scopes, or API configuration settings. Specify the account by ID, or by combination of organization/user, connector, and identifier. Returns the updated account with new token expiry and status information.J\x9a\x01\n\x03\x32\x30\x30\x12\x92\x01\nLConnected account updated successfully with new credentials or configuration\x12\x42\n@\x1a>.scalekit.v1.connected_accounts.UpdateConnectedAccountResponseJg\n\x03\x34\x30\x30\x12`\n^Invalid request - missing required fields, invalid authorization details, or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJK\n\x03\x34\x30\x34\x12\x44\nBConnected account not found - the specified account does not exist\x82\xb5\x18\x03\x18\xc4\x01\x82\xd3\xe4\x93\x02\x1f\x1a\x1a/api/v1/connected_accounts:\x01*\x12\xc6\x06\n\x16\x44\x65leteConnectedAccount\x12=.scalekit.v1.connected_accounts.DeleteConnectedAccountRequest\x1a>.scalekit.v1.connected_accounts.DeleteConnectedAccountResponse\"\xac\x05\x92\x41\xf6\x04\n\x12\x43onnected Accounts\x12\x1a\x44\x65lete a connected account\x1a\x9f\x02Permanently removes a connected account and revokes all associated authentication credentials. Identify the account by ID, or by combination of organization/user, connector, and identifier. This action cannot be undone. All OAuth tokens and API keys for this account will be invalidated.JK\n\x03\x32\x30\x30\x12\x44\nBConnected account deleted successfully and all credentials revokedJD\n\x03\x34\x30\x30\x12=\n;Invalid request - malformed parameters or validation failedJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJK\n\x03\x34\x30\x34\x12\x44\nBConnected account not found - the specified account does not exist\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02&\"!/api/v1/connected_accounts:delete:\x01*\x12\xff\x06\n\x1fGetMagicLinkForConnectedAccount\x12\x46.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountRequest\x1aG.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountResponse\"\xca\x05\x92\x41\x90\x05\n\x12\x43onnected Accounts\x12\"Generate authentication magic link\x1a\xa2\x02\x43reates a time-limited magic link for connecting or re-authorizing a third-party account. The link directs users to the OAuth authorization flow for the specified connector. Returns the generated link URL and expiration timestamp. Links typically expire after a short duration for security.J\x9f\x01\n\x03\x32\x30\x30\x12\x97\x01\nHMagic link generated successfully with authorization URL and expiry time\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetMagicLinkForConnectedAccountResponseJK\n\x03\x34\x30\x30\x12\x44\nBInvalid request - missing required parameters or invalid connectorJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02*\"%/api/v1/connected_accounts/magic_link:\x01*\x12\x85\x06\n\x13GetConnectedAccount\x12:.scalekit.v1.connected_accounts.GetConnectedAccountRequest\x1a;.scalekit.v1.connected_accounts.GetConnectedAccountResponse\"\xf4\x04\x92\x41\x90\x04\n\x12\x43onnected Accounts\x12\x17Get a connected account\x1a\xb8\x01Retrieves a connected account by its unique ID. Use the path \'/this\' (e.g. /api/v1/connected_accounts/this) to retrieve the connected account associated with the current token context.Jv\n\x03\x32\x30\x30\x12o\n,Successfully retrieved the connected account\x12?\n=\x1a;.scalekit.v1.connected_accounts.GetConnectedAccountResponseJD\n\x03\x34\x30\x30\x12=\n;Invalid request - missing or malformed connected account IDJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJ$\n\x03\x34\x30\x34\x12\x1d\n\x1b\x43onnected account not found\x82\xb5\x18\x03\x18\xc4\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x44\x12\x1f/api/v1/connected_accounts/thisZ!\x12\x1f/api/v1/connected_accounts/{id}\x12\xc3\t\n\x1a\x44isconnectConnectedAccount\x12\x41.scalekit.v1.connected_accounts.DisconnectConnectedAccountRequest\x1a\x42.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponse\"\x9d\x08\x92\x41\xee\x06\n\x12\x43onnected Accounts\x12\x1e\x44isconnect a connected account\x1a\xb6\x02\x44isconnects a connected account by setting its status to DISCONNECTED. The account record is retained but marked as no longer active. Use the path \'/this:disconnect\' (e.g. /api/v1/connected_accounts/this:disconnect) to disconnect the account associated with the current token context, without specifying an ID.J\x80\x01\n\x03\x32\x30\x30\x12y\n/Successfully disconnected the connected account\x12\x46\nD\x1a\x42.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponseJ\x99\x01\n\x03\x34\x30\x30\x12\x91\x01\n\x8e\x01Invalid request - malformed connected account ID, or attempting to disconnect an account other than the one bound to the current token contextJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJv\n\x03\x34\x30\x33\x12o\nmForbidden - the token context is bound to a different connected account than the one specified in the requestJ$\n\x03\x34\x30\x34\x12\x1d\n\x1b\x43onnected account not found\x82\xb5\x18\x03\x18\xc4\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x8e\x01\"*/api/v1/connected_accounts/{id}:disconnect:\x01*Z,\"\'/api/v1/connected_accounts/-:disconnect:\x01*Z/\"*/api/v1/connected_accounts/this:disconnect:\x01*\x12\xc2\x04\n\x0eGetRedirectUrl\x12\x35.scalekit.v1.connected_accounts.GetRedirectUrlRequest\x1a\x36.scalekit.v1.connected_accounts.GetRedirectUrlResponse\"\xc0\x03\x92\x41\xf0\x02\n\x12\x43onnected Accounts\x12\x17Get portal redirect URL\x1a\x87\x01Returns the redirect URL for the connected accounts portal. Used to redirect users to the appropriate portal page after authentication.Js\n\x03\x32\x30\x30\x12l\n.Successfully retrieved the portal redirect URL\x12:\n8\x1a\x36.scalekit.v1.connected_accounts.GetRedirectUrlResponseJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access token\x82\xb5\x18\x03\x18\x80\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x30\x12./api/v1/connected_accounts/portal/redirect_url\x12\xbf\x07\n\x17GetConnectedAccountAuth\x12\x46.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierRequest\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponse\"\x92\x06\x92\x41\xe1\x05\n\x12\x43onnected Accounts\x12&Get connected account auth credentials\x1a\xab\x02Retrieves complete authentication details for a connected account including OAuth tokens, refresh tokens, scopes, and API configuration. Query by account ID or by combination of organization/user, connector, and identifier. Returns sensitive credential information - use appropriate access controls.J\xa0\x01\n\x03\x32\x30\x30\x12\x98\x01\nISuccessfully retrieved connected account with full authentication details\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\x03\x34\x30\x30\x12\x35\n3Invalid request - missing required query parametersJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJP\n\x03\x34\x30\x34\x12I\nGConnected account not found - no account matches the specified criteria\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/connected_accounts/auth\x12\xfb\x06\n\x1aGetConnectedAccountDetails\x12\x46.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierRequest\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponse\"\xcb\x05\x92\x41\x97\x05\n\x12\x43onnected Accounts\x12\x1eGet connected account metadata\x1a\x83\x02Returns metadata for a connected account including status, connector type, provider, and configuration without exposing stored authorization credentials. Look up by account ID, or by a combination of organization (or user), connector, and external identifier.J\x86\x01\n\x03\x32\x30\x30\x12\x7f\n0Successfully retrieved connected account details\x12K\nI\x1aG.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\x03\x34\x30\x30\x12\x35\n3Invalid request - missing required query parametersJB\n\x03\x34\x30\x31\x12;\n9Authentication required - missing or invalid access tokenJP\n\x03\x34\x30\x34\x12I\nGConnected account not found - no account matches the specified criteria\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02$\x12\"/api/v1/connected_accounts/details\x12\xbb\x07\n\x1aVerifyConnectedAccountUser\x12\x41.scalekit.v1.connected_accounts.VerifyConnectedAccountUserRequest\x1a\x42.scalekit.v1.connected_accounts.VerifyConnectedAccountUserResponse\"\x95\x06\x92\x41\xda\x05\n\x12\x43onnected Accounts\x12\x1dVerify connected account user\x1a\xa4\x02\x43onfirms the user assertion and activates the connected account after the user completes third-party OAuth. Called by the B2B app server with auth_request_id and identifier. Validates that the asserted identifier matches the one stored on the auth request and promotes pending tokens to live.J\x8a\x01\n\x03\x32\x30\x30\x12\x82\x01\n8Verification successful; connected account is now ACTIVE\x12\x46\nD\x1a\x42.scalekit.v1.connected_accounts.VerifyConnectedAccountUserResponseJ6\n\x03\x34\x30\x30\x12/\n-Invalid request - missing or malformed fieldsJ7\n\x03\x34\x30\x31\x12\x30\n.Unauthorized - invalid or missing access tokenJ(\n\x03\x34\x30\x33\x12!\n\x1f\x46orbidden - identifier mismatchJV\n\x03\x34\x30\x34\x12O\nMNot found - no pending flow for the given auth_request_id or already consumed\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02+\"&/api/v1/connected_accounts/user/verify:\x01*\x1a\xe3\x01\x92\x41\xdf\x01\n\x12\x43onnected Accounts\x12\xc8\x01Manage connected accounts for third-party integrations and OAuth connections. Connected accounts represent authenticated access to external services like Google, Notion, Slack, and other applications.B\xa4\x02Z 0)' _globals['_LISTCONNECTEDACCOUNTSRESPONSE'].fields_by_name['connected_accounts']._loaded_options = None _globals['_LISTCONNECTEDACCOUNTSRESPONSE'].fields_by_name['connected_accounts']._serialized_options = b'\222Aq2oList of connected accounts matching the filter criteria. Excludes sensitive authorization details for security.' _globals['_LISTCONNECTEDACCOUNTSRESPONSE'].fields_by_name['total_size']._loaded_options = None @@ -222,6 +226,8 @@ _globals['_DISCONNECTCONNECTEDACCOUNTREQUEST'].fields_by_name['id']._serialized_options = b'\222Ap2VUnique identifier for the connected account to disconnect. Always prefixed with \'ca_\'.J\026\"ca_24834495392086178\"\272H\006r\004\020\000\030 ' _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE'].fields_by_name['connected_account']._loaded_options = None _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE'].fields_by_name['connected_account']._serialized_options = b'\222A=2;The connected account with its updated DISCONNECTED status.' + _globals['_GETREDIRECTURLRESPONSE'].fields_by_name['redirect_url']._loaded_options = None + _globals['_GETREDIRECTURLRESPONSE'].fields_by_name['redirect_url']._serialized_options = b'\222Ax2AThe URL to redirect the user to in the connected accounts portal.J3\"https://app.example.com/portal/connected-accounts\"' _globals['_CONNECTEDACCOUNTSERVICE']._loaded_options = None _globals['_CONNECTEDACCOUNTSERVICE']._serialized_options = b'\222A\337\001\n\022Connected Accounts\022\310\001Manage connected accounts for third-party integrations and OAuth connections. Connected accounts represent authenticated access to external services like Google, Notion, Slack, and other applications.' _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['ListConnectedAccounts']._loaded_options = None @@ -239,73 +245,79 @@ _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccount']._loaded_options = None _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccount']._serialized_options = b'\222A\220\004\n\022Connected Accounts\022\027Get a connected account\032\270\001Retrieves a connected account by its unique ID. Use the path \'/this\' (e.g. /api/v1/connected_accounts/this) to retrieve the connected account associated with the current token context.Jv\n\003200\022o\n,Successfully retrieved the connected account\022?\n=\032;.scalekit.v1.connected_accounts.GetConnectedAccountResponseJD\n\003400\022=\n;Invalid request - missing or malformed connected account IDJB\n\003401\022;\n9Authentication required - missing or invalid access tokenJ$\n\003404\022\035\n\033Connected account not found\202\265\030\003\030\304\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002D\022\037/api/v1/connected_accounts/thisZ!\022\037/api/v1/connected_accounts/{id}' _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['DisconnectConnectedAccount']._loaded_options = None - _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['DisconnectConnectedAccount']._serialized_options = b'\222A\362\003\n\022Connected Accounts\022\036Disconnect a connected account\032\210\001Disconnects a connected account by setting its status to DISCONNECTED. The account record is retained but is marked as no longer active.J\200\001\n\003200\022y\n/Successfully disconnected the connected account\022F\nD\032B.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponseJD\n\003400\022=\n;Invalid request - missing or malformed connected account IDJB\n\003401\022;\n9Authentication required - missing or invalid access tokenJ$\n\003404\022\035\n\033Connected account not found\202\265\030\003\030\304\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002]\"*/api/v1/connected_accounts/{id}:disconnect:\001*Z,\"\'/api/v1/connected_accounts/-:disconnect:\001*' + _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['DisconnectConnectedAccount']._serialized_options = b'\222A\356\006\n\022Connected Accounts\022\036Disconnect a connected account\032\266\002Disconnects a connected account by setting its status to DISCONNECTED. The account record is retained but marked as no longer active. Use the path \'/this:disconnect\' (e.g. /api/v1/connected_accounts/this:disconnect) to disconnect the account associated with the current token context, without specifying an ID.J\200\001\n\003200\022y\n/Successfully disconnected the connected account\022F\nD\032B.scalekit.v1.connected_accounts.DisconnectConnectedAccountResponseJ\231\001\n\003400\022\221\001\n\216\001Invalid request - malformed connected account ID, or attempting to disconnect an account other than the one bound to the current token contextJB\n\003401\022;\n9Authentication required - missing or invalid access tokenJv\n\003403\022o\nmForbidden - the token context is bound to a different connected account than the one specified in the requestJ$\n\003404\022\035\n\033Connected account not found\202\265\030\003\030\304\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002\216\001\"*/api/v1/connected_accounts/{id}:disconnect:\001*Z,\"\'/api/v1/connected_accounts/-:disconnect:\001*Z/\"*/api/v1/connected_accounts/this:disconnect:\001*' + _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetRedirectUrl']._loaded_options = None + _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetRedirectUrl']._serialized_options = b'\222A\360\002\n\022Connected Accounts\022\027Get portal redirect URL\032\207\001Returns the redirect URL for the connected accounts portal. Used to redirect users to the appropriate portal page after authentication.Js\n\003200\022l\n.Successfully retrieved the portal redirect URL\022:\n8\0326.scalekit.v1.connected_accounts.GetRedirectUrlResponseJB\n\003401\022;\n9Authentication required - missing or invalid access token\202\265\030\003\030\200\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\0020\022./api/v1/connected_accounts/portal/redirect_url' _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccountAuth']._loaded_options = None _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccountAuth']._serialized_options = b'\222A\341\005\n\022Connected Accounts\022&Get connected account auth credentials\032\253\002Retrieves complete authentication details for a connected account including OAuth tokens, refresh tokens, scopes, and API configuration. Query by account ID or by combination of organization/user, connector, and identifier. Returns sensitive credential information - use appropriate access controls.J\240\001\n\003200\022\230\001\nISuccessfully retrieved connected account with full authentication details\022K\nI\032G.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\003400\0225\n3Invalid request - missing required query parametersJB\n\003401\022;\n9Authentication required - missing or invalid access tokenJP\n\003404\022I\nGConnected account not found - no account matches the specified criteria\202\265\030\002\030D\202\323\344\223\002!\022\037/api/v1/connected_accounts/auth' _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccountDetails']._loaded_options = None _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['GetConnectedAccountDetails']._serialized_options = b'\222A\227\005\n\022Connected Accounts\022\036Get connected account metadata\032\203\002Returns metadata for a connected account including status, connector type, provider, and configuration without exposing stored authorization credentials. Look up by account ID, or by a combination of organization (or user), connector, and external identifier.J\206\001\n\003200\022\177\n0Successfully retrieved connected account details\022K\nI\032G.scalekit.v1.connected_accounts.GetConnectedAccountByIdentifierResponseJ<\n\003400\0225\n3Invalid request - missing required query parametersJB\n\003401\022;\n9Authentication required - missing or invalid access tokenJP\n\003404\022I\nGConnected account not found - no account matches the specified criteria\202\265\030\002\030D\202\323\344\223\002$\022\"/api/v1/connected_accounts/details' _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['VerifyConnectedAccountUser']._loaded_options = None _globals['_CONNECTEDACCOUNTSERVICE'].methods_by_name['VerifyConnectedAccountUser']._serialized_options = b'\222A\332\005\n\022Connected Accounts\022\035Verify connected account user\032\244\002Confirms the user assertion and activates the connected account after the user completes third-party OAuth. Called by the B2B app server with auth_request_id and identifier. Validates that the asserted identifier matches the one stored on the auth request and promotes pending tokens to live.J\212\001\n\003200\022\202\001\n8Verification successful; connected account is now ACTIVE\022F\nD\032B.scalekit.v1.connected_accounts.VerifyConnectedAccountUserResponseJ6\n\003400\022/\n-Invalid request - missing or malformed fieldsJ7\n\003401\0220\n.Unauthorized - invalid or missing access tokenJ(\n\003403\022!\n\037Forbidden - identifier mismatchJV\n\003404\022O\nMNot found - no pending flow for the given auth_request_id or already consumed\202\265\030\002\030D\202\323\344\223\002+\"&/api/v1/connected_accounts/user/verify:\001*' - _globals['_CONNECTORSTATUS']._serialized_start=19055 - _globals['_CONNECTORSTATUS']._serialized_end=19194 - _globals['_CONNECTORTYPE']._serialized_start=19197 - _globals['_CONNECTORTYPE']._serialized_end=19376 + _globals['_CONNECTORSTATUS']._serialized_start=19769 + _globals['_CONNECTORSTATUS']._serialized_end=19908 + _globals['_CONNECTORTYPE']._serialized_start=19911 + _globals['_CONNECTORTYPE']._serialized_end=20090 _globals['_LISTCONNECTEDACCOUNTSREQUEST']._serialized_start=359 - _globals['_LISTCONNECTEDACCOUNTSREQUEST']._serialized_end=1920 - _globals['_LISTCONNECTEDACCOUNTSRESPONSE']._serialized_start=1923 - _globals['_LISTCONNECTEDACCOUNTSRESPONSE']._serialized_end=2750 - _globals['_SEARCHCONNECTEDACCOUNTSREQUEST']._serialized_start=2753 - _globals['_SEARCHCONNECTEDACCOUNTSREQUEST']._serialized_end=3617 - _globals['_SEARCHCONNECTEDACCOUNTSRESPONSE']._serialized_start=3620 - _globals['_SEARCHCONNECTEDACCOUNTSRESPONSE']._serialized_end=4267 - _globals['_CREATECONNECTEDACCOUNTREQUEST']._serialized_start=4270 - _globals['_CREATECONNECTEDACCOUNTREQUEST']._serialized_end=5326 - _globals['_CREATECONNECTEDACCOUNTRESPONSE']._serialized_start=5329 - _globals['_CREATECONNECTEDACCOUNTRESPONSE']._serialized_end=5598 - _globals['_UPDATECONNECTEDACCOUNTREQUEST']._serialized_start=5601 - _globals['_UPDATECONNECTEDACCOUNTREQUEST']._serialized_end=6769 - _globals['_UPDATECONNECTEDACCOUNTRESPONSE']._serialized_start=6772 - _globals['_UPDATECONNECTEDACCOUNTRESPONSE']._serialized_end=7019 - _globals['_DELETECONNECTEDACCOUNTREQUEST']._serialized_start=7022 - _globals['_DELETECONNECTEDACCOUNTREQUEST']._serialized_end=7870 - _globals['_DELETECONNECTEDACCOUNTRESPONSE']._serialized_start=7872 - _globals['_DELETECONNECTEDACCOUNTRESPONSE']._serialized_end=7904 - _globals['_GETMAGICLINKFORCONNECTEDACCOUNTREQUEST']._serialized_start=7907 - _globals['_GETMAGICLINKFORCONNECTEDACCOUNTREQUEST']._serialized_end=9154 - _globals['_GETMAGICLINKFORCONNECTEDACCOUNTRESPONSE']._serialized_start=9157 - _globals['_GETMAGICLINKFORCONNECTEDACCOUNTRESPONSE']._serialized_end=9441 - _globals['_VERIFYCONNECTEDACCOUNTUSERREQUEST']._serialized_start=9444 - _globals['_VERIFYCONNECTEDACCOUNTUSERREQUEST']._serialized_end=9807 - _globals['_VERIFYCONNECTEDACCOUNTUSERRESPONSE']._serialized_start=9810 - _globals['_VERIFYCONNECTEDACCOUNTUSERRESPONSE']._serialized_end=10021 - _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERREQUEST']._serialized_start=10024 - _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERREQUEST']._serialized_end=10871 - _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERRESPONSE']._serialized_start=10874 - _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERRESPONSE']._serialized_end=11192 - _globals['_CONNECTEDACCOUNT']._serialized_start=11195 - _globals['_CONNECTEDACCOUNT']._serialized_end=13726 - _globals['_CREATECONNECTEDACCOUNT']._serialized_start=13729 - _globals['_CREATECONNECTEDACCOUNT']._serialized_end=14523 - _globals['_UPDATECONNECTEDACCOUNT']._serialized_start=14526 - _globals['_UPDATECONNECTEDACCOUNT']._serialized_end=15226 - _globals['_CONNECTEDACCOUNTFORLIST']._serialized_start=15229 - _globals['_CONNECTEDACCOUNTFORLIST']._serialized_end=16349 - _globals['_AUTHORIZATIONDETAILS']._serialized_start=16352 - _globals['_AUTHORIZATIONDETAILS']._serialized_end=16623 - _globals['_GOOGLEDWDAUTH']._serialized_start=16626 - _globals['_GOOGLEDWDAUTH']._serialized_end=17226 - _globals['_OAUTHTOKEN']._serialized_start=17229 - _globals['_OAUTHTOKEN']._serialized_end=17961 - _globals['_STATICAUTH']._serialized_start=17964 - _globals['_STATICAUTH']._serialized_end=18208 - _globals['_GETCONNECTEDACCOUNTREQUEST']._serialized_start=18211 - _globals['_GETCONNECTEDACCOUNTREQUEST']._serialized_end=18470 - _globals['_GETCONNECTEDACCOUNTRESPONSE']._serialized_start=18473 - _globals['_GETCONNECTEDACCOUNTRESPONSE']._serialized_end=18670 - _globals['_DISCONNECTCONNECTEDACCOUNTREQUEST']._serialized_start=18673 - _globals['_DISCONNECTCONNECTEDACCOUNTREQUEST']._serialized_end=18851 - _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE']._serialized_start=18854 - _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE']._serialized_end=19052 - _globals['_CONNECTEDACCOUNTSERVICE']._serialized_start=19379 - _globals['_CONNECTEDACCOUNTSERVICE']._serialized_end=29523 + _globals['_LISTCONNECTEDACCOUNTSREQUEST']._serialized_end=2421 + _globals['_LISTCONNECTEDACCOUNTSRESPONSE']._serialized_start=2424 + _globals['_LISTCONNECTEDACCOUNTSRESPONSE']._serialized_end=3251 + _globals['_SEARCHCONNECTEDACCOUNTSREQUEST']._serialized_start=3254 + _globals['_SEARCHCONNECTEDACCOUNTSREQUEST']._serialized_end=4118 + _globals['_SEARCHCONNECTEDACCOUNTSRESPONSE']._serialized_start=4121 + _globals['_SEARCHCONNECTEDACCOUNTSRESPONSE']._serialized_end=4768 + _globals['_CREATECONNECTEDACCOUNTREQUEST']._serialized_start=4771 + _globals['_CREATECONNECTEDACCOUNTREQUEST']._serialized_end=5827 + _globals['_CREATECONNECTEDACCOUNTRESPONSE']._serialized_start=5830 + _globals['_CREATECONNECTEDACCOUNTRESPONSE']._serialized_end=6099 + _globals['_UPDATECONNECTEDACCOUNTREQUEST']._serialized_start=6102 + _globals['_UPDATECONNECTEDACCOUNTREQUEST']._serialized_end=7270 + _globals['_UPDATECONNECTEDACCOUNTRESPONSE']._serialized_start=7273 + _globals['_UPDATECONNECTEDACCOUNTRESPONSE']._serialized_end=7520 + _globals['_DELETECONNECTEDACCOUNTREQUEST']._serialized_start=7523 + _globals['_DELETECONNECTEDACCOUNTREQUEST']._serialized_end=8371 + _globals['_DELETECONNECTEDACCOUNTRESPONSE']._serialized_start=8373 + _globals['_DELETECONNECTEDACCOUNTRESPONSE']._serialized_end=8405 + _globals['_GETMAGICLINKFORCONNECTEDACCOUNTREQUEST']._serialized_start=8408 + _globals['_GETMAGICLINKFORCONNECTEDACCOUNTREQUEST']._serialized_end=9655 + _globals['_GETMAGICLINKFORCONNECTEDACCOUNTRESPONSE']._serialized_start=9658 + _globals['_GETMAGICLINKFORCONNECTEDACCOUNTRESPONSE']._serialized_end=9942 + _globals['_VERIFYCONNECTEDACCOUNTUSERREQUEST']._serialized_start=9945 + _globals['_VERIFYCONNECTEDACCOUNTUSERREQUEST']._serialized_end=10308 + _globals['_VERIFYCONNECTEDACCOUNTUSERRESPONSE']._serialized_start=10311 + _globals['_VERIFYCONNECTEDACCOUNTUSERRESPONSE']._serialized_end=10522 + _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERREQUEST']._serialized_start=10525 + _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERREQUEST']._serialized_end=11372 + _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERRESPONSE']._serialized_start=11375 + _globals['_GETCONNECTEDACCOUNTBYIDENTIFIERRESPONSE']._serialized_end=11693 + _globals['_CONNECTEDACCOUNT']._serialized_start=11696 + _globals['_CONNECTEDACCOUNT']._serialized_end=14227 + _globals['_CREATECONNECTEDACCOUNT']._serialized_start=14230 + _globals['_CREATECONNECTEDACCOUNT']._serialized_end=15024 + _globals['_UPDATECONNECTEDACCOUNT']._serialized_start=15027 + _globals['_UPDATECONNECTEDACCOUNT']._serialized_end=15727 + _globals['_CONNECTEDACCOUNTFORLIST']._serialized_start=15730 + _globals['_CONNECTEDACCOUNTFORLIST']._serialized_end=16850 + _globals['_AUTHORIZATIONDETAILS']._serialized_start=16853 + _globals['_AUTHORIZATIONDETAILS']._serialized_end=17124 + _globals['_GOOGLEDWDAUTH']._serialized_start=17127 + _globals['_GOOGLEDWDAUTH']._serialized_end=17727 + _globals['_OAUTHTOKEN']._serialized_start=17730 + _globals['_OAUTHTOKEN']._serialized_end=18462 + _globals['_STATICAUTH']._serialized_start=18465 + _globals['_STATICAUTH']._serialized_end=18709 + _globals['_GETCONNECTEDACCOUNTREQUEST']._serialized_start=18712 + _globals['_GETCONNECTEDACCOUNTREQUEST']._serialized_end=18971 + _globals['_GETCONNECTEDACCOUNTRESPONSE']._serialized_start=18974 + _globals['_GETCONNECTEDACCOUNTRESPONSE']._serialized_end=19171 + _globals['_DISCONNECTCONNECTEDACCOUNTREQUEST']._serialized_start=19174 + _globals['_DISCONNECTCONNECTEDACCOUNTREQUEST']._serialized_end=19352 + _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE']._serialized_start=19355 + _globals['_DISCONNECTCONNECTEDACCOUNTRESPONSE']._serialized_end=19553 + _globals['_GETREDIRECTURLREQUEST']._serialized_start=19555 + _globals['_GETREDIRECTURLREQUEST']._serialized_end=19578 + _globals['_GETREDIRECTURLRESPONSE']._serialized_start=19581 + _globals['_GETREDIRECTURLRESPONSE']._serialized_end=19766 + _globals['_CONNECTEDACCOUNTSERVICE']._serialized_start=20093 + _globals['_CONNECTEDACCOUNTSERVICE']._serialized_end=31248 # @@protoc_insertion_point(module_scope) diff --git a/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi b/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi index 05886ea..683e86e 100644 --- a/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi +++ b/scalekit/v1/connected_accounts/connected_accounts_pb2.pyi @@ -53,7 +53,7 @@ TRELLO_OAUTH1: ConnectorType GOOGLE_DWD: ConnectorType class ListConnectedAccountsRequest(_message.Message): - __slots__ = ("organization_id", "user_id", "connector", "identifier", "provider", "page_size", "page_token", "query") + __slots__ = ("organization_id", "user_id", "connector", "identifier", "provider", "page_size", "page_token", "query", "connection_names") ORGANIZATION_ID_FIELD_NUMBER: _ClassVar[int] USER_ID_FIELD_NUMBER: _ClassVar[int] CONNECTOR_FIELD_NUMBER: _ClassVar[int] @@ -62,6 +62,7 @@ class ListConnectedAccountsRequest(_message.Message): PAGE_SIZE_FIELD_NUMBER: _ClassVar[int] PAGE_TOKEN_FIELD_NUMBER: _ClassVar[int] QUERY_FIELD_NUMBER: _ClassVar[int] + CONNECTION_NAMES_FIELD_NUMBER: _ClassVar[int] organization_id: str user_id: str connector: str @@ -70,7 +71,8 @@ class ListConnectedAccountsRequest(_message.Message): page_size: int page_token: str query: str - def __init__(self, organization_id: _Optional[str] = ..., user_id: _Optional[str] = ..., connector: _Optional[str] = ..., identifier: _Optional[str] = ..., provider: _Optional[str] = ..., page_size: _Optional[int] = ..., page_token: _Optional[str] = ..., query: _Optional[str] = ...) -> None: ... + connection_names: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, organization_id: _Optional[str] = ..., user_id: _Optional[str] = ..., connector: _Optional[str] = ..., identifier: _Optional[str] = ..., provider: _Optional[str] = ..., page_size: _Optional[int] = ..., page_token: _Optional[str] = ..., query: _Optional[str] = ..., connection_names: _Optional[_Iterable[str]] = ...) -> None: ... class ListConnectedAccountsResponse(_message.Message): __slots__ = ("connected_accounts", "total_size", "next_page_token", "prev_page_token") @@ -359,3 +361,13 @@ class DisconnectConnectedAccountResponse(_message.Message): CONNECTED_ACCOUNT_FIELD_NUMBER: _ClassVar[int] connected_account: ConnectedAccount def __init__(self, connected_account: _Optional[_Union[ConnectedAccount, _Mapping]] = ...) -> None: ... + +class GetRedirectUrlRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class GetRedirectUrlResponse(_message.Message): + __slots__ = ("redirect_url",) + REDIRECT_URL_FIELD_NUMBER: _ClassVar[int] + redirect_url: str + def __init__(self, redirect_url: _Optional[str] = ...) -> None: ... diff --git a/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py b/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py index 53109b7..5b4b5ff 100644 --- a/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py +++ b/scalekit/v1/connected_accounts/connected_accounts_pb2_grpc.py @@ -54,6 +54,11 @@ def __init__(self, channel): request_serializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.DisconnectConnectedAccountRequest.SerializeToString, response_deserializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.DisconnectConnectedAccountResponse.FromString, ) + self.GetRedirectUrl = channel.unary_unary( + '/scalekit.v1.connected_accounts.ConnectedAccountService/GetRedirectUrl', + request_serializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlRequest.SerializeToString, + response_deserializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlResponse.FromString, + ) self.GetConnectedAccountAuth = channel.unary_unary( '/scalekit.v1.connected_accounts.ConnectedAccountService/GetConnectedAccountAuth', request_serializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetConnectedAccountByIdentifierRequest.SerializeToString, @@ -130,6 +135,13 @@ def DisconnectConnectedAccount(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def GetRedirectUrl(self, request, context): + """Get Redirect URL for Connected Account Portal + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def GetConnectedAccountAuth(self, request, context): """Get Connected Account Authentication Details """ @@ -194,6 +206,11 @@ def add_ConnectedAccountServiceServicer_to_server(servicer, server): request_deserializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.DisconnectConnectedAccountRequest.FromString, response_serializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.DisconnectConnectedAccountResponse.SerializeToString, ), + 'GetRedirectUrl': grpc.unary_unary_rpc_method_handler( + servicer.GetRedirectUrl, + request_deserializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlRequest.FromString, + response_serializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlResponse.SerializeToString, + ), 'GetConnectedAccountAuth': grpc.unary_unary_rpc_method_handler( servicer.GetConnectedAccountAuth, request_deserializer=scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetConnectedAccountByIdentifierRequest.FromString, @@ -355,6 +372,23 @@ def DisconnectConnectedAccount(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def GetRedirectUrl(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/scalekit.v1.connected_accounts.ConnectedAccountService/GetRedirectUrl', + scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlRequest.SerializeToString, + scalekit_dot_v1_dot_connected__accounts_dot_connected__accounts__pb2.GetRedirectUrlResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def GetConnectedAccountAuth(request, target, diff --git a/scalekit/v1/mcp/mcp_pb2.py b/scalekit/v1/mcp/mcp_pb2.py index 069520d..55dc804 100644 --- a/scalekit/v1/mcp/mcp_pb2.py +++ b/scalekit/v1/mcp/mcp_pb2.py @@ -16,6 +16,7 @@ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 from google.api import visibility_pb2 as google_dot_api_dot_visibility__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 @@ -24,7 +25,7 @@ from scalekit.v1.options import options_pb2 as scalekit_dot_v1_dot_options_dot_options__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19scalekit/v1/mcp/mcp.proto\x12\x0fscalekit.v1.mcp\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a!scalekit/v1/options/options.proto\"q\n\x10\x43reateMcpRequest\x12]\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB5\x92\x41,2*MCP tool configuration to create or update\xbaH\x03\xc8\x01\x01R\x03mcp\"X\n\x11\x43reateMcpResponse\x12\x43\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB\x1b\x92\x41\x18\x32\x16The MCP server detailsR\x03mcp\"\x93\x03\n\x03Mcp\x12\x38\n\x02id\x18\x01 \x01(\tB(\x92\x41\"2\x15Unique ID of the toolJ\t\"res_123\"\xe0\x41\x03R\x02id\x12x\n\rtool_mappings\x18\x02 \x03(\x0b\x32\x1c.scalekit.v1.mcp.ToolMappingB5\x92\x41\'2\x1bProvider name (e.g. GOOGLE)J\x08\"GOOGLE\"\xbaH\x08\x92\x01\x02\x08\x01\xc8\x01\x01R\x0ctoolMappings\x12\x84\x01\n\x1c\x63onnected_account_identifier\x18\x03 \x01(\tBB\x92\x41\x35\x32$Identifier for the connected accountJ\r\"account_123\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x1a\x63onnectedAccountIdentifier\x12Q\n\x03url\x18\x04 \x01(\tB?\x92\x41\x39\x32\x15Unique ID of the toolJ \"https://example.com/mcp/v1/abc\"\xe0\x41\x03R\x03url\"\x96\x02\n\x0bToolMapping\x12\\\n\ntool_names\x18\x01 \x03(\tB=\x92\x41:2\x12List of tool namesJ$[\"GMAIL_FETCH_MAILS\", \"LIST_DRAFTS\"]R\ttoolNames\x12\\\n\x0f\x63onnection_name\x18\x02 \x01(\tB3\x92\x41*2\x1c\x43onnection name for the toolJ\n\"MY-GMAIL\"\xbaH\x03\xc8\x01\x01R\x0e\x63onnectionName\x12K\n\x06status\x18\x03 \x01(\tB3\x92\x41-2!Authentication status of the toolJ\x08\"ACTIVE\"\xe0\x41\x03R\x06status\"L\n\rGetMcpRequest\x12;\n\x06mcp_id\x18\x01 \x01(\tB$\x92\x41\x1b\x32\x19ID of the MCP to retrieve\xbaH\x03\xc8\x01\x01R\x05mcpId\"N\n\x0eGetMcpResponse\x12<\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB\x14\x92\x41\x11\x32\x0fThe MCP detailsR\x03mcp\"\x84\x02\n\x0eListMcpRequest\x12>\n\x06\x66ilter\x18\x01 \x01(\x0b\x32&.scalekit.v1.mcp.ListMcpRequest.FilterR\x06\x66ilter\x1a\xb1\x01\n\x06\x46ilter\x12m\n\x1c\x63onnected_account_identifier\x18\x01 \x01(\tB+\x92\x41(2&Filter by connected account identifierR\x1a\x63onnectedAccountIdentifier\x12\x38\n\nlink_token\x18\x02 \x01(\tB\x19\x92\x41\x16\x32\x14\x46ilter by link tokenR\tlinkToken\"N\n\x0fListMcpResponse\x12;\n\x04mcps\x18\x01 \x03(\x0b\x32\x14.scalekit.v1.mcp.McpB\x11\x92\x41\x0e\x32\x0cList of MCPsR\x04mcps\"M\n\x10\x44\x65leteMcpRequest\x12\x39\n\x06mcp_id\x18\x01 \x01(\tB\"\x92\x41\x19\x32\x17ID of the MCP to delete\xbaH\x03\xc8\x01\x01R\x05mcpId\"\x13\n\x11\x44\x65leteMcpResponse\"|\n\x16\x43reateMcpConfigRequest\x12\x62\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB.\x92\x41%2#MCP configuration details to create\xbaH\x03\xc8\x01\x01R\x06\x63onfig\"q\n\x17\x43reateMcpConfigResponse\x12V\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\"\x92\x41\x1f\x32\x1dThe created MCP configurationR\x06\x63onfig\"\xaf\x03\n\x16UpdateMcpConfigRequest\x12j\n\tconfig_id\x18\x01 \x01(\tBM\x92\x41@2%ID of the MCP configuration to updateJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\x12w\n\x0b\x64\x65scription\x18\x02 \x01(\tBU\x92\x41R2-Updated description for the MCP configurationJ!\"Updated daily summarizer config\"R\x0b\x64\x65scription\x12\xaf\x01\n\x18\x63onnection_tool_mappings\x18\x03 \x03(\x0b\x32/.scalekit.v1.mcp.McpConfigConnectionToolMappingBD\x92\x41\x41\x32?Updated list of connection-to-tool mappings for this MCP configR\x16\x63onnectionToolMappings\"q\n\x17UpdateMcpConfigResponse\x12V\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\"\x92\x41\x1f\x32\x1dThe updated MCP configurationR\x06\x63onfig\"\x84\x01\n\x16\x44\x65leteMcpConfigRequest\x12j\n\tconfig_id\x18\x01 \x01(\tBM\x92\x41@2%ID of the MCP configuration to deleteJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\"\x19\n\x17\x44\x65leteMcpConfigResponse\"\x80\x01\n\x13GetMcpConfigRequest\x12i\n\tconfig_id\x18\x01 \x01(\tBL\x92\x41?2$ID of the MCP configuration to fetchJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\"p\n\x14GetMcpConfigResponse\x12X\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB$\x92\x41!2\x1fThe requested MCP configurationR\x06\x63onfig\"\xc5\x04\n\x15ListMcpConfigsRequest\x12\x45\n\x06\x66ilter\x18\x01 \x01(\x0b\x32-.scalekit.v1.mcp.ListMcpConfigsRequest.FilterR\x06\x66ilter\x12\x42\n\x06search\x18\x02 \x01(\tB*\x92\x41\'2%Look ahead text search on config nameR\x06search\x12V\n\tpage_size\x18\x03 \x01(\rB9\x92\x41/2-Number of configs to return per page (max 30)\xbaH\x04*\x02\x18\x1eR\x08pageSize\x12W\n\npage_token\x18\x04 \x01(\tB8\x92\x41\x35\x32\x33Pagination token to fetch the next or previous pageR\tpageToken\x1a\xef\x01\n\x06\x46ilter\x12\x33\n\x02id\x18\x01 \x01(\tB#\x92\x41 2\x1e\x46ilter by MCP configuration idR\x02id\x12\x64\n\x04name\x18\x02 \x01(\tBP\x92\x41M2KCase-insensitive prefix search on configuration name (minimum 3 characters)R\x04name\x12J\n\x08provider\x18\x03 \x01(\tB.\x92\x41+2)Filter configs that include this providerR\x08provider\"\xf0\x02\n\x16ListMcpConfigsResponse\x12U\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\x1f\x92\x41\x1c\x32\x1aList of MCP configurationsR\x07\x63onfigs\x12T\n\x0fnext_page_token\x18\x02 \x01(\tB,\x92\x41)2\'Pagination token to fetch the next pageR\rnextPageToken\x12X\n\x0fprev_page_token\x18\x03 \x01(\tB0\x92\x41-2+Pagination token to fetch the previous pageR\rprevPageToken\x12O\n\ntotal_size\x18\x04 \x01(\rB0\x92\x41-2+Total number of configs matching the filterR\ttotalSize\"\xe8\x02\n\x18\x45nsureMcpInstanceRequest\x12J\n\x04name\x18\x01 \x01(\tB6\x92\x41\x33\x32!Display name for the MCP instanceJ\x0e\"daily-digest\"R\x04name\x12\x80\x01\n\x0b\x63onfig_name\x18\x02 \x01(\tB_\x92\x41R2ID of the MCP instance whose connection statuses are requestedJ\x18\"inst_88630864544790977\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\ninstanceId\x12u\n\x12include_auth_links\x18\x02 \x01(\x08\x42G\x92\x41\x44\x32\x42Whether to generate fresh authentication links for each connectionR\x10includeAuthLinks\"\xc1\x04\n\x1eMcpInstanceConnectionAuthState\x12J\n\rconnection_id\x18\x01 \x01(\tB%\x92\x41\"2 Underlying connection identifierR\x0c\x63onnectionId\x12P\n\x0f\x63onnection_name\x18\x02 \x01(\tB\'\x92\x41$2\"Developer-assigned connection nameR\x0e\x63onnectionName\x12@\n\x08provider\x18\x03 \x01(\tB$\x92\x41!2\x1fProvider backing the connectionR\x08provider\x12_\n\x14\x63onnected_account_id\x18\x04 \x01(\tB-\x92\x41*2(Connected account backing the connectionR\x12\x63onnectedAccountId\x12u\n\x18\x63onnected_account_status\x18\x05 \x01(\tB;\x92\x41\x38\x32\x36\x43urrent authentication status of the connected accountR\x16\x63onnectedAccountStatus\x12g\n\x13\x61uthentication_link\x18\x06 \x01(\tB6\x92\x41\x33\x32\x31Magic link for reconnecting the connected accountR\x12\x61uthenticationLink\"\xac\x01\n\x1fGetMcpInstanceAuthStateResponse\x12\x88\x01\n\x0b\x63onnections\x18\x01 \x03(\x0b\x32/.scalekit.v1.mcp.McpInstanceConnectionAuthStateB5\x92\x41\x32\x32\x30Status of each connection mapped to the instanceR\x0b\x63onnections\"\xf0\x05\n\x0bMcpInstance\x12O\n\x02id\x18\x01 \x01(\tB?\x92\x41\x39\x32\x1dUnique ID of the MCP instanceJ\x18\"inst_88630864544790977\"\xe0\x41\x03R\x02id\x12K\n\x04name\x18\x02 \x01(\tB7\x92\x41.2\x1c\x44isplay name of the instanceJ\x0e\"daily-digest\"\xbaH\x03\xc8\x01\x01R\x04name\x12|\n\x0fuser_identifier\x18\x03 \x01(\tBS\x92\x41J26Identifier for the user who owns or uses this instanceJ\x10\"akshay.parihar\"\xbaH\x03\xc8\x01\x01R\x0euserIdentifier\x12\\\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB(\x92\x41%2#Configuration backing this instanceR\x06\x63onfig\x12\x84\x01\n\x0clast_used_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampBF\x92\x41\x43\x32)Timestamp when the instance was last usedJ\x16\"0001-01-01T00:00:00Z\"R\nlastUsedAt\x12\x84\x01\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampBI\x92\x41\x46\x32,Timestamp when the instance was last updatedJ\x16\"2025-10-07T12:21:00Z\"R\tupdatedAt\x12Y\n\x03url\x18\x07 \x01(\tBG\x92\x41\x44\x32\x1dURL to reach the MCP instanceJ#\"https://example.com/mcp/v1/abc123\"R\x03url\"\xdc\x03\n\tMcpConfig\x12L\n\x02id\x18\x01 \x01(\tB<\x92\x41\x36\x32\x1bUnique ID of the MCP configJ\x17\"cfg_85630864460904897\"\xe0\x41\x03R\x02id\x12\\\n\x04name\x18\x02 \x01(\tBH\x92\x41;2%Unique name for the MCP configurationJ\x12\"daily-summarizer\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x04name\x12y\n\x0b\x64\x65scription\x18\x03 \x01(\tBW\x92\x41T2$Description of the MCP configurationJ,\"Summarizes daily emails and posts to Slack\"R\x0b\x64\x65scription\x12\xa7\x01\n\x18\x63onnection_tool_mappings\x18\x04 \x03(\x0b\x32/.scalekit.v1.mcp.McpConfigConnectionToolMappingB<\x92\x41\x39\x32\x37List of connection-to-tool mappings for this MCP configR\x16\x63onnectionToolMappings\"\x95\x05\n\x1eMcpConfigConnectionToolMapping\x12H\n\rconnection_id\x18\x01 \x01(\tB#\x92\x41\x1d\x32\x1bUnique ID of the connection\xe0\x41\x03R\x0c\x63onnectionId\x12V\n\x0f\x63onnection_name\x18\x02 \x01(\tB-\x92\x41$2\"Developer-assigned connection name\xbaH\x03\xc8\x01\x01R\x0e\x63onnectionName\x12\x45\n\x08provider\x18\x03 \x01(\tB)\x92\x41#2!Provider name for this connection\xe0\x41\x03R\x08provider\x12[\n\x05tools\x18\x04 \x03(\tBE\x92\x41\x42\x32@List of tool names linked to this connection (empty = all tools)R\x05tools\x12\x81\x01\n\x14\x63onnected_account_id\x18\x05 \x01(\tBJ\x92\x41G2EConnected account backing this connection in the MCP instance contextH\x00R\x12\x63onnectedAccountId\x88\x01\x01\x12s\n\x18\x63onnected_account_status\x18\x06 \x01(\tB4\x92\x41\x31\x32/Authentication status for the connected accountH\x01R\x16\x63onnectedAccountStatus\x88\x01\x01\x42\x17\n\x15_connected_account_idB\x1b\n\x19_connected_account_status2\x9d!\n\nMcpService\x12\xa8\x02\n\tCreateMcp\x12!.scalekit.v1.mcp.CreateMcpRequest\x1a\".scalekit.v1.mcp.CreateMcpResponse\"\xd3\x01\x92\x41\xb1\x01\n\x03mcp\x12\x41\x43reates or returns the existing MCP with the given configuration.\x1agCreates a new MCP for the configuration. If same configuration exists, it will return the existing MCP.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x12\"\x0b/api/v1/mcp:\x03mcp\x12\xbe\x01\n\x06GetMcp\x12\x1e.scalekit.v1.mcp.GetMcpRequest\x1a\x1f.scalekit.v1.mcp.GetMcpResponse\"s\x92\x41N\n\x03mcp\x12\x1aGet an existing MCP by ID.\x1a+Returns the existing MCP with the given ID.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x16\x12\x14/api/v1/mcp/{mcp_id}\x12\xf9\x01\n\x07ListMcp\x12\x1f.scalekit.v1.mcp.ListMcpRequest\x1a .scalekit.v1.mcp.ListMcpResponse\"\xaa\x01\x92\x41\x8d\x01\n\x03mcp\x12 List MCPs with optional filters.\x1a\x64Returns a list of existing MCPs, optionally filtered by connected_account_identifier and link_token.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\r\x12\x0b/api/v1/mcp\x12\xb8\x01\n\tDeleteMcp\x12!.scalekit.v1.mcp.DeleteMcpRequest\x1a\".scalekit.v1.mcp.DeleteMcpResponse\"d\x92\x41?\n\x03mcp\x12\x14\x44\x65lete an MCP by ID.\x1a\"Deletes the MCP with the given ID.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x16*\x14/api/v1/mcp/{mcp_id}\x12\x86\x02\n\x0f\x43reateMcpConfig\x12\'.scalekit.v1.mcp.CreateMcpConfigRequest\x1a(.scalekit.v1.mcp.CreateMcpConfigResponse\"\x9f\x01\x92\x41s\n\x0bmcp-configs\x12\x1e\x43reate a new MCP configuration\x1a\x44\x43reates a new MCP configuration with a set of connections and tools.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1d\"\x13/api/v1/mcp/configs:\x06\x63onfig\x12\xb1\x02\n\x0fUpdateMcpConfig\x12\'.scalekit.v1.mcp.UpdateMcpConfigRequest\x1a(.scalekit.v1.mcp.UpdateMcpConfigResponse\"\xca\x01\x92\x41\x96\x01\n\x0bmcp-configs\x12$Update an existing MCP configuration\x1a\x61Updates the name, description, and connection-to-tool mappings for an existing MCP configuration.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02$\x1a\x1f/api/v1/mcp/configs/{config_id}:\x01*\x12\x9e\x02\n\x0eListMcpConfigs\x12&.scalekit.v1.mcp.ListMcpConfigsRequest\x1a\'.scalekit.v1.mcp.ListMcpConfigsResponse\"\xba\x01\x92\x41\x95\x01\n\x0bmcp-configs\x12\x17List MCP configurations\x1amLists MCP configurations for the current environment with optional filters for id, name prefix, and provider.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x15\x12\x13/api/v1/mcp/configs\x12\xfe\x01\n\x0cGetMcpConfig\x12$.scalekit.v1.mcp.GetMcpConfigRequest\x1a%.scalekit.v1.mcp.GetMcpConfigResponse\"\xa0\x01\x92\x41p\n\x0bmcp-configs\x12\x1a\x46\x65tch an MCP configuration\x1a\x45Returns a single MCP configuration for the current environment by ID.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/mcp/configs/{config_id}\x12\xa7\x02\n\x0f\x44\x65leteMcpConfig\x12\'.scalekit.v1.mcp.DeleteMcpConfigRequest\x1a(.scalekit.v1.mcp.DeleteMcpConfigResponse\"\xc0\x01\x92\x41\x8f\x01\n\x0bmcp-configs\x12\x1b\x44\x65lete an MCP configuration\x1a\x63\x44\x65letes the MCP configuration and any associated mappings and instances in the current environment.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!*\x1f/api/v1/mcp/configs/{config_id}\x12\xbd\x02\n\x11\x45nsureMcpInstance\x12).scalekit.v1.mcp.EnsureMcpInstanceRequest\x1a*.scalekit.v1.mcp.EnsureMcpInstanceResponse\"\xd0\x01\x92\x41\xa6\x01\n\rmcp-instances\x12\x1dGet or create an MCP instance\x1avReturns an existing MCP instance for the given configuration, name, and user identifier or creates one if none exists.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1a\"\x15/api/v1/mcp/instances:\x01*\x12\xd2\x02\n\x10ListMcpInstances\x12(.scalekit.v1.mcp.ListMcpInstancesRequest\x1a).scalekit.v1.mcp.ListMcpInstancesResponse\"\xe8\x01\x92\x41\xc1\x01\n\rmcp-instances\x12\x12List MCP instances\x1a\x9b\x01Lists MCP instances for the current environment with optional filters for instance id, name, configuration, and text search across name or user identifier.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x17\x12\x15/api/v1/mcp/instances\x12\x83\x02\n\x11\x44\x65leteMcpInstance\x12).scalekit.v1.mcp.DeleteMcpInstanceRequest\x1a*.scalekit.v1.mcp.DeleteMcpInstanceResponse\"\x96\x01\x92\x41\x62\n\rmcp-instances\x12\x16\x44\x65lete an MCP instance\x1a\x39\x44\x65letes a single MCP instance in the current environment.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02%*#/api/v1/mcp/instances/{instance_id}\x12\xc9\x02\n\x11UpdateMcpInstance\x12).scalekit.v1.mcp.UpdateMcpInstanceRequest\x1a*.scalekit.v1.mcp.UpdateMcpInstanceResponse\"\xdc\x01\x92\x41\xa4\x01\n\rmcp-instances\x12\x16Update an MCP instance\x1a{Updates attributes of an MCP instance. Currently only the config name can be changed, which rebuilds the instance mappings.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02(2#/api/v1/mcp/instances/{instance_id}:\x01*\x12\x80\x02\n\x0eGetMcpInstance\x12&.scalekit.v1.mcp.GetMcpInstanceRequest\x1a\'.scalekit.v1.mcp.GetMcpInstanceResponse\"\x9c\x01\x92\x41h\n\rmcp-instances\x12\x15\x46\x65tch an MCP instance\x1a@Returns a single MCP instance for the current environment by ID.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02%\x12#/api/v1/mcp/instances/{instance_id}\x12\xf8\x02\n\x17GetMcpInstanceAuthState\x12/.scalekit.v1.mcp.GetMcpInstanceAuthStateRequest\x1a\x30.scalekit.v1.mcp.GetMcpInstanceAuthStateResponse\"\xf9\x01\x92\x41\xb5\x01\n\rmcp-instances\x12/Fetch connection auth state for an MCP instance\x1asReturns the connected account status and fresh authentication links for each connection mapped to the MCP instance.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x34\"2/api/v1/mcp/instances/{instance_id}:get_auth_stateB/Z-github.com/scalekit-inc/scalekit/pkg/grpc/mcpb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19scalekit/v1/mcp/mcp.proto\x12\x0fscalekit.v1.mcp\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a!scalekit/v1/options/options.proto\"q\n\x10\x43reateMcpRequest\x12]\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB5\x92\x41,2*MCP tool configuration to create or update\xbaH\x03\xc8\x01\x01R\x03mcp\"X\n\x11\x43reateMcpResponse\x12\x43\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB\x1b\x92\x41\x18\x32\x16The MCP server detailsR\x03mcp\"\x93\x03\n\x03Mcp\x12\x38\n\x02id\x18\x01 \x01(\tB(\x92\x41\"2\x15Unique ID of the toolJ\t\"res_123\"\xe0\x41\x03R\x02id\x12x\n\rtool_mappings\x18\x02 \x03(\x0b\x32\x1c.scalekit.v1.mcp.ToolMappingB5\x92\x41\'2\x1bProvider name (e.g. GOOGLE)J\x08\"GOOGLE\"\xbaH\x08\x92\x01\x02\x08\x01\xc8\x01\x01R\x0ctoolMappings\x12\x84\x01\n\x1c\x63onnected_account_identifier\x18\x03 \x01(\tBB\x92\x41\x35\x32$Identifier for the connected accountJ\r\"account_123\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x1a\x63onnectedAccountIdentifier\x12Q\n\x03url\x18\x04 \x01(\tB?\x92\x41\x39\x32\x15Unique ID of the toolJ \"https://example.com/mcp/v1/abc\"\xe0\x41\x03R\x03url\"\x96\x02\n\x0bToolMapping\x12\\\n\ntool_names\x18\x01 \x03(\tB=\x92\x41:2\x12List of tool namesJ$[\"GMAIL_FETCH_MAILS\", \"LIST_DRAFTS\"]R\ttoolNames\x12\\\n\x0f\x63onnection_name\x18\x02 \x01(\tB3\x92\x41*2\x1c\x43onnection name for the toolJ\n\"MY-GMAIL\"\xbaH\x03\xc8\x01\x01R\x0e\x63onnectionName\x12K\n\x06status\x18\x03 \x01(\tB3\x92\x41-2!Authentication status of the toolJ\x08\"ACTIVE\"\xe0\x41\x03R\x06status\"L\n\rGetMcpRequest\x12;\n\x06mcp_id\x18\x01 \x01(\tB$\x92\x41\x1b\x32\x19ID of the MCP to retrieve\xbaH\x03\xc8\x01\x01R\x05mcpId\"N\n\x0eGetMcpResponse\x12<\n\x03mcp\x18\x01 \x01(\x0b\x32\x14.scalekit.v1.mcp.McpB\x14\x92\x41\x11\x32\x0fThe MCP detailsR\x03mcp\"\x84\x02\n\x0eListMcpRequest\x12>\n\x06\x66ilter\x18\x01 \x01(\x0b\x32&.scalekit.v1.mcp.ListMcpRequest.FilterR\x06\x66ilter\x1a\xb1\x01\n\x06\x46ilter\x12m\n\x1c\x63onnected_account_identifier\x18\x01 \x01(\tB+\x92\x41(2&Filter by connected account identifierR\x1a\x63onnectedAccountIdentifier\x12\x38\n\nlink_token\x18\x02 \x01(\tB\x19\x92\x41\x16\x32\x14\x46ilter by link tokenR\tlinkToken\"N\n\x0fListMcpResponse\x12;\n\x04mcps\x18\x01 \x03(\x0b\x32\x14.scalekit.v1.mcp.McpB\x11\x92\x41\x0e\x32\x0cList of MCPsR\x04mcps\"M\n\x10\x44\x65leteMcpRequest\x12\x39\n\x06mcp_id\x18\x01 \x01(\tB\"\x92\x41\x19\x32\x17ID of the MCP to delete\xbaH\x03\xc8\x01\x01R\x05mcpId\"\x13\n\x11\x44\x65leteMcpResponse\"|\n\x16\x43reateMcpConfigRequest\x12\x62\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB.\x92\x41%2#MCP configuration details to create\xbaH\x03\xc8\x01\x01R\x06\x63onfig\"q\n\x17\x43reateMcpConfigResponse\x12V\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\"\x92\x41\x1f\x32\x1dThe created MCP configurationR\x06\x63onfig\"\xcc\x03\n\x16UpdateMcpConfigRequest\x12j\n\tconfig_id\x18\x01 \x01(\tBM\x92\x41@2%ID of the MCP configuration to updateJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\x12w\n\x0b\x64\x65scription\x18\x02 \x01(\tBU\x92\x41R2-Updated description for the MCP configurationJ!\"Updated daily summarizer config\"R\x0b\x64\x65scription\x12\xcc\x01\n\x18\x63onnection_tool_mappings\x18\x03 \x03(\x0b\x32/.scalekit.v1.mcp.McpConfigConnectionToolMappingBa\x92\x41V2TUpdated list of connection-to-tool mappings for this MCP config. Maximum 25 entries.\xbaH\x05\x92\x01\x02\x10\x19R\x16\x63onnectionToolMappings\"q\n\x17UpdateMcpConfigResponse\x12V\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\"\x92\x41\x1f\x32\x1dThe updated MCP configurationR\x06\x63onfig\"\x84\x01\n\x16\x44\x65leteMcpConfigRequest\x12j\n\tconfig_id\x18\x01 \x01(\tBM\x92\x41@2%ID of the MCP configuration to deleteJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\"\x19\n\x17\x44\x65leteMcpConfigResponse\"\x80\x01\n\x13GetMcpConfigRequest\x12i\n\tconfig_id\x18\x01 \x01(\tBL\x92\x41?2$ID of the MCP configuration to fetchJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\"p\n\x14GetMcpConfigResponse\x12X\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB$\x92\x41!2\x1fThe requested MCP configurationR\x06\x63onfig\"\xfd\x06\n\x15ListMcpConfigsRequest\x12\x45\n\x06\x66ilter\x18\x01 \x01(\x0b\x32-.scalekit.v1.mcp.ListMcpConfigsRequest.FilterR\x06\x66ilter\x12\x42\n\x06search\x18\x02 \x01(\tB*\x92\x41\'2%Look ahead text search on config nameR\x06search\x12V\n\tpage_size\x18\x03 \x01(\rB9\x92\x41/2-Number of configs to return per page (max 30)\xbaH\x04*\x02\x18\x1eR\x08pageSize\x12W\n\npage_token\x18\x04 \x01(\tB8\x92\x41\x35\x32\x33Pagination token to fetch the next or previous pageR\tpageToken\x1a\xa7\x04\n\x06\x46ilter\x12\x33\n\x02id\x18\x01 \x01(\tB#\x92\x41 2\x1e\x46ilter by MCP configuration idR\x02id\x12\xe0\x01\n\x04name\x18\x02 \x01(\tB\xcb\x01\x92\x41\xae\x01\x32\xa9\x01\x43\x61se-insensitive exact match on configuration name. Allowed characters: letters (a\xe2\x80\x93z, A\xe2\x80\x93Z), digits (0\xe2\x80\x93\x39), hyphens (-), and underscores (_). Maximum 100 characters.xd\xbaH\x16r\x14\x18\x64\x32\x10^[a-zA-Z0-9_-]*$R\x04name\x12J\n\x08provider\x18\x03 \x01(\tB.\x92\x41+2)Filter configs that include this providerR\x08provider\x12\xb8\x01\n\x0emcp_server_url\x18\x04 \x01(\tB\x91\x01\x92\x41\x8d\x01\x32\x8a\x01\x46ilter configs by MCP server URL. The UUID is extracted from the last path segment of the URL and used to find the matching configuration.R\x0cmcpServerUrl\"\xf0\x02\n\x16ListMcpConfigsResponse\x12U\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB\x1f\x92\x41\x1c\x32\x1aList of MCP configurationsR\x07\x63onfigs\x12T\n\x0fnext_page_token\x18\x02 \x01(\tB,\x92\x41)2\'Pagination token to fetch the next pageR\rnextPageToken\x12X\n\x0fprev_page_token\x18\x03 \x01(\tB0\x92\x41-2+Pagination token to fetch the previous pageR\rprevPageToken\x12O\n\ntotal_size\x18\x04 \x01(\rB0\x92\x41-2+Total number of configs matching the filterR\ttotalSize\"\xef\x02\n\x18\x45nsureMcpInstanceRequest\x12J\n\x04name\x18\x01 \x01(\tB6\x92\x41\x33\x32!Display name for the MCP instanceJ\x0e\"daily-digest\"R\x04name\x12\x80\x01\n\x0b\x63onfig_name\x18\x02 \x01(\tB_\x92\x41R2\n\rconnection_id\x18\x01 \x01(\tB\x19\x92\x41\x16\x32\x14ID of the connectionR\x0c\x63onnectionId\x12\x44\n\x0f\x63onnection_name\x18\x02 \x01(\tB\x1b\x92\x41\x18\x32\x16Name of the connectionR\x0e\x63onnectionName\x12G\n\x08provider\x18\x03 \x01(\tB+\x92\x41(2&Provider identifier for the connectionR\x08provider\x12t\n\x14\x63onnected_account_id\x18\x04 \x01(\tB=\x92\x41:28ID of the connected account for this user and connectionH\x00R\x12\x63onnectedAccountId\x88\x01\x01\x12r\n\x18\x63onnected_account_status\x18\x05 \x01(\tB3\x92\x41\x30\x32.Authentication status of the connected accountH\x01R\x16\x63onnectedAccountStatus\x88\x01\x01\x12\xc1\x01\n\x13\x61uthentication_link\x18\x06 \x01(\tB\x8f\x01\x92\x41\x8b\x01\x32\x88\x01\x46resh authentication link for the connected account. Empty when include_auth_link is false or when the connection has no associated key.R\x12\x61uthenticationLinkB\x17\n\x15_connected_account_idB\x1b\n\x19_connected_account_status\"\xb0\x04\n\x1fListMcpConnectedAccountsRequest\x12`\n\tconfig_id\x18\x01 \x01(\tBC\x92\x41\x36\x32\x1bID of the MCP configurationJ\x17\"cfg_85630864460904897\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\x08\x63onfigId\x12\x8a\x01\n\nidentifier\x18\x02 \x01(\tBj\x92\x41Z2@Identifier for the end user whose connected accounts to retrieveJ\x16\"john.doe@example.com\"\xe0\x41\x02\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\nidentifier\x12\x9d\x02\n\x11include_auth_link\x18\x03 \x01(\x08\x42\xf0\x01\x92\x41\xec\x01\x32\xe9\x01When true, generates a fresh authentication link for each connection and creates connected accounts if they do not exist. When false or omitted, returns existing connected account status without creating accounts or generating links.R\x0fincludeAuthLink\"\xc2\x01\n ListMcpConnectedAccountsResponse\x12\x9d\x01\n\x12\x63onnected_accounts\x18\x01 \x03(\x0b\x32\'.scalekit.v1.mcp.McpConnectionAuthStateBE\x92\x41\x42\x32@Connected account state for each connection in the configurationR\x11\x63onnectedAccounts\"\x83\x05\n\x17ListMcpInstancesRequest\x12G\n\x06\x66ilter\x18\x01 \x01(\x0b\x32/.scalekit.v1.mcp.ListMcpInstancesRequest.FilterR\x06\x66ilter\x12h\n\x06search\x18\x02 \x01(\tBP\x92\x41M2KCase-insensitive look-ahead search across instance name and user identifierR\x06search\x12X\n\tpage_size\x18\x03 \x01(\rB;\x92\x41\x31\x32/Number of instances to return per page (max 30)\xbaH\x04*\x02\x18\x1eR\x08pageSize\x12W\n\npage_token\x18\x04 \x01(\tB8\x92\x41\x35\x32\x33Pagination token to fetch the next or previous pageR\tpageToken\x1a\x81\x02\n\x06\x46ilter\x12.\n\x02id\x18\x01 \x01(\tB\x1e\x92\x41\x1b\x32\x19\x46ilter by MCP instance idR\x02id\x12\x36\n\x04name\x18\x02 \x01(\tB\"\x92\x41\x1f\x32\x1d\x46ilter by exact instance nameR\x04name\x12\x46\n\x0b\x63onfig_name\x18\x03 \x01(\tB%\x92\x41\"2 Filter by MCP configuration nameR\nconfigName\x12G\n\x0fuser_identifier\x18\x04 \x01(\tB\x1e\x92\x41\x1b\x32\x19\x46ilter by user identifierR\x0euserIdentifier\"\xf5\x02\n\x18ListMcpInstancesResponse\x12V\n\tinstances\x18\x01 \x03(\x0b\x32\x1c.scalekit.v1.mcp.McpInstanceB\x1a\x92\x41\x17\x32\x15List of MCP instancesR\tinstances\x12T\n\x0fnext_page_token\x18\x02 \x01(\tB,\x92\x41)2\'Pagination token to fetch the next pageR\rnextPageToken\x12X\n\x0fprev_page_token\x18\x03 \x01(\tB0\x92\x41-2+Pagination token to fetch the previous pageR\rprevPageToken\x12Q\n\ntotal_size\x18\x04 \x01(\rB2\x92\x41/2-Total number of instances matching the filterR\ttotalSize\"\x86\x01\n\x18\x44\x65leteMcpInstanceRequest\x12j\n\x0binstance_id\x18\x01 \x01(\tBI\x92\x41<2 ID of the MCP instance to deleteJ\x18\"inst_88630864544790977\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\ninstanceId\"\x1b\n\x19\x44\x65leteMcpInstanceResponse\"\xce\x02\n\x18UpdateMcpInstanceRequest\x12j\n\x0binstance_id\x18\x01 \x01(\tBI\x92\x41<2 ID of the MCP instance to updateJ\x18\"inst_88630864544790977\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\ninstanceId\x12V\n\x04name\x18\x02 \x01(\tBB\x92\x41?2%New display name for the MCP instanceJ\x16\"daily-digest-updated\"R\x04name\x12n\n\x0b\x63onfig_name\x18\x03 \x01(\tBM\x92\x41J24New MCP configuration name to attach to the instanceJ\x12\"daily-summarizer\"R\nconfigName\"p\n\x19UpdateMcpInstanceResponse\x12S\n\x08instance\x18\x01 \x01(\x0b\x32\x1c.scalekit.v1.mcp.McpInstanceB\x19\x92\x41\x16\x32\x14Updated MCP instanceR\x08instance\"\x82\x01\n\x15GetMcpInstanceRequest\x12i\n\x0binstance_id\x18\x01 \x01(\tBH\x92\x41;2\x1fID of the MCP instance to fetchJ\x18\"inst_88630864544790977\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\ninstanceId\"s\n\x16GetMcpInstanceResponse\x12Y\n\x08instance\x18\x01 \x01(\x0b\x32\x1c.scalekit.v1.mcp.McpInstanceB\x1f\x92\x41\x1c\x32\x1aThe requested MCP instanceR\x08instance\"\xa2\x02\n\x1eGetMcpInstanceAuthStateRequest\x12\x88\x01\n\x0binstance_id\x18\x01 \x01(\tBg\x92\x41Z2>ID of the MCP instance whose connection statuses are requestedJ\x18\"inst_88630864544790977\"\xbaH\x07r\x02\x10\x01\xc8\x01\x01R\ninstanceId\x12u\n\x12include_auth_links\x18\x02 \x01(\x08\x42G\x92\x41\x44\x32\x42Whether to generate fresh authentication links for each connectionR\x10includeAuthLinks\"\xc1\x04\n\x1eMcpInstanceConnectionAuthState\x12J\n\rconnection_id\x18\x01 \x01(\tB%\x92\x41\"2 Underlying connection identifierR\x0c\x63onnectionId\x12P\n\x0f\x63onnection_name\x18\x02 \x01(\tB\'\x92\x41$2\"Developer-assigned connection nameR\x0e\x63onnectionName\x12@\n\x08provider\x18\x03 \x01(\tB$\x92\x41!2\x1fProvider backing the connectionR\x08provider\x12_\n\x14\x63onnected_account_id\x18\x04 \x01(\tB-\x92\x41*2(Connected account backing the connectionR\x12\x63onnectedAccountId\x12u\n\x18\x63onnected_account_status\x18\x05 \x01(\tB;\x92\x41\x38\x32\x36\x43urrent authentication status of the connected accountR\x16\x63onnectedAccountStatus\x12g\n\x13\x61uthentication_link\x18\x06 \x01(\tB6\x92\x41\x33\x32\x31Magic link for reconnecting the connected accountR\x12\x61uthenticationLink\"\xac\x01\n\x1fGetMcpInstanceAuthStateResponse\x12\x88\x01\n\x0b\x63onnections\x18\x01 \x03(\x0b\x32/.scalekit.v1.mcp.McpInstanceConnectionAuthStateB5\x92\x41\x32\x32\x30Status of each connection mapped to the instanceR\x0b\x63onnections\"\xf7\x05\n\x0bMcpInstance\x12O\n\x02id\x18\x01 \x01(\tB?\x92\x41\x39\x32\x1dUnique ID of the MCP instanceJ\x18\"inst_88630864544790977\"\xe0\x41\x03R\x02id\x12K\n\x04name\x18\x02 \x01(\tB7\x92\x41.2\x1c\x44isplay name of the instanceJ\x0e\"daily-digest\"\xbaH\x03\xc8\x01\x01R\x04name\x12\x82\x01\n\x0fuser_identifier\x18\x03 \x01(\tBY\x92\x41P26Identifier for the user who owns or uses this instanceJ\x16\"john.doe@example.com\"\xbaH\x03\xc8\x01\x01R\x0euserIdentifier\x12\\\n\x06\x63onfig\x18\x04 \x01(\x0b\x32\x1a.scalekit.v1.mcp.McpConfigB(\x92\x41%2#Configuration backing this instanceR\x06\x63onfig\x12\x84\x01\n\x0clast_used_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampBF\x92\x41\x43\x32)Timestamp when the instance was last usedJ\x16\"0001-01-01T00:00:00Z\"R\nlastUsedAt\x12\x84\x01\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampBI\x92\x41\x46\x32,Timestamp when the instance was last updatedJ\x16\"2025-10-07T12:21:00Z\"R\tupdatedAt\x12Y\n\x03url\x18\x07 \x01(\tBG\x92\x41\x44\x32\x1dURL to reach the MCP instanceJ#\"https://example.com/mcp/v1/abc123\"R\x03url\"\x93\x07\n\tMcpConfig\x12L\n\x02id\x18\x01 \x01(\tB<\x92\x41\x36\x32\x1bUnique ID of the MCP configJ\x17\"cfg_85630864460904897\"\xe0\x41\x03R\x02id\x12\xf3\x01\n\x04name\x18\x02 \x01(\tB\xde\x01\x92\x41\xbf\x01\x32\xa3\x01Unique name for the MCP configuration. Must be 1\xe2\x80\x93\x31\x30\x30 characters. Allowed characters: lowercase letters (a\xe2\x80\x93z), digits (0\xe2\x80\x93\x39), hyphens (-), and underscores (_).J\x12\"daily-summarizer\"xd\x80\x01\x01\xbaH\x18r\x13\x10\x01\x18\x64\x32\r^[a-z0-9_-]+$\xc8\x01\x01R\x04name\x12y\n\x0b\x64\x65scription\x18\x03 \x01(\tBW\x92\x41T2$Description of the MCP configurationJ,\"Summarizes daily emails and posts to Slack\"R\x0b\x64\x65scription\x12\xc4\x01\n\x18\x63onnection_tool_mappings\x18\x04 \x03(\x0b\x32/.scalekit.v1.mcp.McpConfigConnectionToolMappingBY\x92\x41N2LList of connection-to-tool mappings for this MCP config. Maximum 25 entries.\xbaH\x05\x92\x01\x02\x10\x19R\x16\x63onnectionToolMappings\x12\xff\x01\n\x0emcp_server_url\x18\x05 \x01(\tB\xd8\x01\x92\x41\xd1\x01\x32\x7fURL of the MCP server for this configuration. Empty when the MCP config server URL feature is not enabled for this environment.JN\"https://env.scalekit.com/mcp/v3/servers/550e8400-e29b-41d4-a716-446655440000\"\xe0\x41\x03R\x0cmcpServerUrl\"\x95\x05\n\x1eMcpConfigConnectionToolMapping\x12H\n\rconnection_id\x18\x01 \x01(\tB#\x92\x41\x1d\x32\x1bUnique ID of the connection\xe0\x41\x03R\x0c\x63onnectionId\x12V\n\x0f\x63onnection_name\x18\x02 \x01(\tB-\x92\x41$2\"Developer-assigned connection name\xbaH\x03\xc8\x01\x01R\x0e\x63onnectionName\x12\x45\n\x08provider\x18\x03 \x01(\tB)\x92\x41#2!Provider name for this connection\xe0\x41\x03R\x08provider\x12[\n\x05tools\x18\x04 \x03(\tBE\x92\x41\x42\x32@List of tool names linked to this connection (empty = all tools)R\x05tools\x12\x81\x01\n\x14\x63onnected_account_id\x18\x05 \x01(\tBJ\x92\x41G2EConnected account backing this connection in the MCP instance contextH\x00R\x12\x63onnectedAccountId\x88\x01\x01\x12s\n\x18\x63onnected_account_status\x18\x06 \x01(\tB4\x92\x41\x31\x32/Authentication status for the connected accountH\x01R\x16\x63onnectedAccountStatus\x88\x01\x01\x42\x17\n\x15_connected_account_idB\x1b\n\x19_connected_account_status\"\xb5\x05\n\x1c\x43reateMcpSessionTokenRequest\x12\xcc\x01\n\rmcp_config_id\x18\x01 \x01(\tB\xa7\x01\x92\x41\x99\x01\x32~Unique ID of the MCP configuration whose connections back the token. The configuration must exist in the caller\'s environment.J\x17\"cfg_85630864460904897\"\xe0\x41\x02\xbaH\x04r\x02\x10\x01R\x0bmcpConfigId\x12\xaf\x02\n\nidentifier\x18\x02 \x01(\tB\x8e\x02\x92\x41\xfd\x01\x32\xe2\x01Upstream-provider identifier (typically the user\'s email or provider user-id) shared by the connected accounts the token represents. A single identifier can map to one connected account per connection in the MCP configuration.J\x10\"alice@acme.com\"x\xff\x01\x80\x01\x01\xe0\x41\x02\xbaH\x07r\x05\x10\x01\x18\xff\x01R\nidentifier\x12\x93\x01\n\x06\x65xpiry\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationB`\x92\x41]2ROptional token lifetime. Must be between 60s and 24h. Defaults to 1h when omitted.J\x07\"3600s\"R\x06\x65xpiry\"\xff\x04\n\x1d\x43reateMcpSessionTokenResponse\x12\xd3\x03\n\x05token\x18\x01 \x01(\tB\xbc\x03\x92\x41\xb5\x03\x32\xb2\x02Signed JWT (RS256) whose `sub` claim is the supplied identifier and whose `aud` claim is the MCP server URL bound to the configuration. Payload also carries the MCP configuration ID (`mcp_cfg`) and the resolved connected-account IDs (`ca_ids`). Signed with the calling environment\'s active JWT signing key.J~\"eyJhbGciOiJSUzI1NiIsImtpZCI6InNua18xMjMifQ.eyJhdWQiOlsiYWxpY2VAYWNtZS5jb20iXSwidG9rZW5fdHlwZSI6Im1jcF9zZXNzaW9uIn0.signature\"\xe0\x41\x03R\x05token\x12\x87\x01\n\nexpires_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampBL\x92\x41\x46\x32\x44\x41\x62solute time at which the token expires. Equals issued_at + expiry.\xe0\x41\x03R\texpiresAt2\xcd\x34\n\nMcpService\x12\xa8\x02\n\tCreateMcp\x12!.scalekit.v1.mcp.CreateMcpRequest\x1a\".scalekit.v1.mcp.CreateMcpResponse\"\xd3\x01\x92\x41\xb1\x01\n\x03mcp\x12\x41\x43reates or returns the existing MCP with the given configuration.\x1agCreates a new MCP for the configuration. If same configuration exists, it will return the existing MCP.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x12\"\x0b/api/v1/mcp:\x03mcp\x12\xbe\x01\n\x06GetMcp\x12\x1e.scalekit.v1.mcp.GetMcpRequest\x1a\x1f.scalekit.v1.mcp.GetMcpResponse\"s\x92\x41N\n\x03mcp\x12\x1aGet an existing MCP by ID.\x1a+Returns the existing MCP with the given ID.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x16\x12\x14/api/v1/mcp/{mcp_id}\x12\xf9\x01\n\x07ListMcp\x12\x1f.scalekit.v1.mcp.ListMcpRequest\x1a .scalekit.v1.mcp.ListMcpResponse\"\xaa\x01\x92\x41\x8d\x01\n\x03mcp\x12 List MCPs with optional filters.\x1a\x64Returns a list of existing MCPs, optionally filtered by connected_account_identifier and link_token.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\r\x12\x0b/api/v1/mcp\x12\xb8\x01\n\tDeleteMcp\x12!.scalekit.v1.mcp.DeleteMcpRequest\x1a\".scalekit.v1.mcp.DeleteMcpResponse\"d\x92\x41?\n\x03mcp\x12\x14\x44\x65lete an MCP by ID.\x1a\"Deletes the MCP with the given ID.\x82\xb5\x18\x02\x18\x64\x82\xd3\xe4\x93\x02\x16*\x14/api/v1/mcp/{mcp_id}\x12\x86\x02\n\x0f\x43reateMcpConfig\x12\'.scalekit.v1.mcp.CreateMcpConfigRequest\x1a(.scalekit.v1.mcp.CreateMcpConfigResponse\"\x9f\x01\x92\x41s\n\x0bmcp-configs\x12\x1e\x43reate a new MCP configuration\x1a\x44\x43reates a new MCP configuration with a set of connections and tools.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1d\"\x13/api/v1/mcp/configs:\x06\x63onfig\x12\xb1\x02\n\x0fUpdateMcpConfig\x12\'.scalekit.v1.mcp.UpdateMcpConfigRequest\x1a(.scalekit.v1.mcp.UpdateMcpConfigResponse\"\xca\x01\x92\x41\x96\x01\n\x0bmcp-configs\x12$Update an existing MCP configuration\x1a\x61Updates the name, description, and connection-to-tool mappings for an existing MCP configuration.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02$\x1a\x1f/api/v1/mcp/configs/{config_id}:\x01*\x12\x9e\x02\n\x0eListMcpConfigs\x12&.scalekit.v1.mcp.ListMcpConfigsRequest\x1a\'.scalekit.v1.mcp.ListMcpConfigsResponse\"\xba\x01\x92\x41\x95\x01\n\x0bmcp-configs\x12\x17List MCP configurations\x1amLists MCP configurations for the current environment with optional filters for id, name prefix, and provider.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x15\x12\x13/api/v1/mcp/configs\x12\xfe\x01\n\x0cGetMcpConfig\x12$.scalekit.v1.mcp.GetMcpConfigRequest\x1a%.scalekit.v1.mcp.GetMcpConfigResponse\"\xa0\x01\x92\x41p\n\x0bmcp-configs\x12\x1a\x46\x65tch an MCP configuration\x1a\x45Returns a single MCP configuration for the current environment by ID.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/mcp/configs/{config_id}\x12\xa7\x02\n\x0f\x44\x65leteMcpConfig\x12\'.scalekit.v1.mcp.DeleteMcpConfigRequest\x1a(.scalekit.v1.mcp.DeleteMcpConfigResponse\"\xc0\x01\x92\x41\x8f\x01\n\x0bmcp-configs\x12\x1b\x44\x65lete an MCP configuration\x1a\x63\x44\x65letes the MCP configuration and any associated mappings and instances in the current environment.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02!*\x1f/api/v1/mcp/configs/{config_id}\x12\xbd\x02\n\x11\x45nsureMcpInstance\x12).scalekit.v1.mcp.EnsureMcpInstanceRequest\x1a*.scalekit.v1.mcp.EnsureMcpInstanceResponse\"\xd0\x01\x92\x41\xa6\x01\n\rmcp-instances\x12\x1dGet or create an MCP instance\x1avReturns an existing MCP instance for the given configuration, name, and user identifier or creates one if none exists.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x1a\"\x15/api/v1/mcp/instances:\x01*\x12\xd2\x02\n\x10ListMcpInstances\x12(.scalekit.v1.mcp.ListMcpInstancesRequest\x1a).scalekit.v1.mcp.ListMcpInstancesResponse\"\xe8\x01\x92\x41\xc1\x01\n\rmcp-instances\x12\x12List MCP instances\x1a\x9b\x01Lists MCP instances for the current environment with optional filters for instance id, name, configuration, and text search across name or user identifier.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x17\x12\x15/api/v1/mcp/instances\x12\x83\x02\n\x11\x44\x65leteMcpInstance\x12).scalekit.v1.mcp.DeleteMcpInstanceRequest\x1a*.scalekit.v1.mcp.DeleteMcpInstanceResponse\"\x96\x01\x92\x41\x62\n\rmcp-instances\x12\x16\x44\x65lete an MCP instance\x1a\x39\x44\x65letes a single MCP instance in the current environment.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02%*#/api/v1/mcp/instances/{instance_id}\x12\xc9\x02\n\x11UpdateMcpInstance\x12).scalekit.v1.mcp.UpdateMcpInstanceRequest\x1a*.scalekit.v1.mcp.UpdateMcpInstanceResponse\"\xdc\x01\x92\x41\xa4\x01\n\rmcp-instances\x12\x16Update an MCP instance\x1a{Updates attributes of an MCP instance. Currently only the config name can be changed, which rebuilds the instance mappings.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02(2#/api/v1/mcp/instances/{instance_id}:\x01*\x12\x80\x02\n\x0eGetMcpInstance\x12&.scalekit.v1.mcp.GetMcpInstanceRequest\x1a\'.scalekit.v1.mcp.GetMcpInstanceResponse\"\x9c\x01\x92\x41h\n\rmcp-instances\x12\x15\x46\x65tch an MCP instance\x1a@Returns a single MCP instance for the current environment by ID.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02%\x12#/api/v1/mcp/instances/{instance_id}\x12\xf8\x02\n\x17GetMcpInstanceAuthState\x12/.scalekit.v1.mcp.GetMcpInstanceAuthStateRequest\x1a\x30.scalekit.v1.mcp.GetMcpInstanceAuthStateResponse\"\xf9\x01\x92\x41\xb5\x01\n\rmcp-instances\x12/Fetch connection auth state for an MCP instance\x1asReturns the connected account status and fresh authentication links for each connection mapped to the MCP instance.\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x34\"2/api/v1/mcp/instances/{instance_id}:get_auth_state\x12\xa2\n\n\x15\x43reateMcpSessionToken\x12-.scalekit.v1.mcp.CreateMcpSessionTokenRequest\x1a..scalekit.v1.mcp.CreateMcpSessionTokenResponse\"\xa9\t\x92\x41\xea\x08\n\x0bmcp-configs\x12\x1b\x43reate an MCP session token\x1a\xdf\x04Mints a short-lived JWT that represents a user identifier across the connected accounts associated with an MCP configuration. The supplied identifier becomes the token\'s `sub` claim; the token\'s `aud` claim is the MCP server URL bound to the configuration. Claims also carry the MCP configuration ID (`mcp_cfg`) and the list of resolved connected-account IDs (`ca_ids`). Use this operation to issue a single credential an MCP server can present on the user\'s behalf when calling provider tools. The mint fails if any connection mapped to the configuration has no active connected account for the identifier.J\x88\x01\n\x03\x32\x30\x30\x12\x80\x01\nJToken created successfully; returns the signed JWT and its absolute expiry\x12\x32\n0\x1a..scalekit.v1.mcp.CreateMcpSessionTokenResponseJ\xed\x01\n\x03\x34\x30\x30\x12\xe5\x01\n\xe2\x01Invalid request - mcp_config_id or identifier is missing or malformed, expiry is outside the 60s-24h window, the MCP configuration has no connections, or a connection has no active connected account for the supplied identifierJa\n\x03\x34\x30\x34\x12Z\nXNot Found - no MCP configuration exists with the supplied ID in the caller\'s environment\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02/\"*/api/v1/mcp/configs/{mcp_config_id}/tokens:\x01*\x12\x88\t\n\x18ListMcpConnectedAccounts\x12\x30.scalekit.v1.mcp.ListMcpConnectedAccountsRequest\x1a\x31.scalekit.v1.mcp.ListMcpConnectedAccountsResponse\"\x86\x08\x92\x41\xbf\x07\n\x0bmcp-configs\x12\x30List connected accounts for an MCP configuration\x1a\xdf\x04Returns the connected account state for each connection in the MCP configuration for the given user identifier. When include_auth_link is true, creates connected accounts on the fly if they do not exist and returns a fresh authentication link per connection. When include_auth_link is false or omitted, returns the current status of existing connected accounts only \xe2\x80\x94 no accounts are created and authentication_link is always empty. Authentication links are only present when the connection has an associated key; if the connection has no key, authentication_link is empty regardless of include_auth_link.J\x8a\x01\n\x03\x32\x30\x30\x12\x82\x01\nIConnected account state returned for each connection in the configuration\x12\x35\n3\x1a\x31.scalekit.v1.mcp.ListMcpConnectedAccountsResponseJD\n\x03\x34\x30\x30\x12=\n;Bad request - config_id or identifier is missing or invalidJI\n\x03\x34\x30\x34\x12\x42\n@Not found - no MCP configuration exists with the given config_id\x82\xb5\x18\x02\x18\x44\x82\xd3\xe4\x93\x02\x37\"2/api/v1/mcp/configs/{config_id}/connected_accounts:\x01*B/Z-github.com/scalekit-inc/scalekit/pkg/grpc/mcpb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -71,7 +72,7 @@ _globals['_UPDATEMCPCONFIGREQUEST'].fields_by_name['description']._loaded_options = None _globals['_UPDATEMCPCONFIGREQUEST'].fields_by_name['description']._serialized_options = b'\222AR2-Updated description for the MCP configurationJ!\"Updated daily summarizer config\"' _globals['_UPDATEMCPCONFIGREQUEST'].fields_by_name['connection_tool_mappings']._loaded_options = None - _globals['_UPDATEMCPCONFIGREQUEST'].fields_by_name['connection_tool_mappings']._serialized_options = b'\222AA2?Updated list of connection-to-tool mappings for this MCP config' + _globals['_UPDATEMCPCONFIGREQUEST'].fields_by_name['connection_tool_mappings']._serialized_options = b'\222AV2TUpdated list of connection-to-tool mappings for this MCP config. Maximum 25 entries.\272H\005\222\001\002\020\031' _globals['_UPDATEMCPCONFIGRESPONSE'].fields_by_name['config']._loaded_options = None _globals['_UPDATEMCPCONFIGRESPONSE'].fields_by_name['config']._serialized_options = b'\222A\0372\035The updated MCP configuration' _globals['_DELETEMCPCONFIGREQUEST'].fields_by_name['config_id']._loaded_options = None @@ -83,9 +84,11 @@ _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['id']._loaded_options = None _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['id']._serialized_options = b'\222A 2\036Filter by MCP configuration id' _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['name']._loaded_options = None - _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['name']._serialized_options = b'\222AM2KCase-insensitive prefix search on configuration name (minimum 3 characters)' + _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['name']._serialized_options = b'\222A\256\0012\251\001Case-insensitive exact match on configuration name. Allowed characters: letters (a\342\200\223z, A\342\200\223Z), digits (0\342\200\2239), hyphens (-), and underscores (_). Maximum 100 characters.xd\272H\026r\024\030d2\020^[a-zA-Z0-9_-]*$' _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['provider']._loaded_options = None _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['provider']._serialized_options = b'\222A+2)Filter configs that include this provider' + _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['mcp_server_url']._loaded_options = None + _globals['_LISTMCPCONFIGSREQUEST_FILTER'].fields_by_name['mcp_server_url']._serialized_options = b'\222A\215\0012\212\001Filter configs by MCP server URL. The UUID is extracted from the last path segment of the URL and used to find the matching configuration.' _globals['_LISTMCPCONFIGSREQUEST'].fields_by_name['search']._loaded_options = None _globals['_LISTMCPCONFIGSREQUEST'].fields_by_name['search']._serialized_options = b'\222A\'2%Look ahead text search on config name' _globals['_LISTMCPCONFIGSREQUEST'].fields_by_name['page_size']._loaded_options = None @@ -105,9 +108,29 @@ _globals['_ENSUREMCPINSTANCEREQUEST'].fields_by_name['config_name']._loaded_options = None _globals['_ENSUREMCPINSTANCEREQUEST'].fields_by_name['config_name']._serialized_options = b'\222AR2 None: ... + mcp_server_url: str + def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., provider: _Optional[str] = ..., mcp_server_url: _Optional[str] = ...) -> None: ... FILTER_FIELD_NUMBER: _ClassVar[int] SEARCH_FIELD_NUMBER: _ClassVar[int] PAGE_SIZE_FIELD_NUMBER: _ClassVar[int] @@ -189,6 +192,38 @@ class EnsureMcpInstanceResponse(_message.Message): instance: McpInstance def __init__(self, instance: _Optional[_Union[McpInstance, _Mapping]] = ...) -> None: ... +class McpConnectionAuthState(_message.Message): + __slots__ = ("connection_id", "connection_name", "provider", "connected_account_id", "connected_account_status", "authentication_link") + CONNECTION_ID_FIELD_NUMBER: _ClassVar[int] + CONNECTION_NAME_FIELD_NUMBER: _ClassVar[int] + PROVIDER_FIELD_NUMBER: _ClassVar[int] + CONNECTED_ACCOUNT_ID_FIELD_NUMBER: _ClassVar[int] + CONNECTED_ACCOUNT_STATUS_FIELD_NUMBER: _ClassVar[int] + AUTHENTICATION_LINK_FIELD_NUMBER: _ClassVar[int] + connection_id: str + connection_name: str + provider: str + connected_account_id: str + connected_account_status: str + authentication_link: str + def __init__(self, connection_id: _Optional[str] = ..., connection_name: _Optional[str] = ..., provider: _Optional[str] = ..., connected_account_id: _Optional[str] = ..., connected_account_status: _Optional[str] = ..., authentication_link: _Optional[str] = ...) -> None: ... + +class ListMcpConnectedAccountsRequest(_message.Message): + __slots__ = ("config_id", "identifier", "include_auth_link") + CONFIG_ID_FIELD_NUMBER: _ClassVar[int] + IDENTIFIER_FIELD_NUMBER: _ClassVar[int] + INCLUDE_AUTH_LINK_FIELD_NUMBER: _ClassVar[int] + config_id: str + identifier: str + include_auth_link: bool + def __init__(self, config_id: _Optional[str] = ..., identifier: _Optional[str] = ..., include_auth_link: bool = ...) -> None: ... + +class ListMcpConnectedAccountsResponse(_message.Message): + __slots__ = ("connected_accounts",) + CONNECTED_ACCOUNTS_FIELD_NUMBER: _ClassVar[int] + connected_accounts: _containers.RepeatedCompositeFieldContainer[McpConnectionAuthState] + def __init__(self, connected_accounts: _Optional[_Iterable[_Union[McpConnectionAuthState, _Mapping]]] = ...) -> None: ... + class ListMcpInstancesRequest(_message.Message): __slots__ = ("filter", "search", "page_size", "page_token") class Filter(_message.Message): @@ -311,16 +346,18 @@ class McpInstance(_message.Message): def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., user_identifier: _Optional[str] = ..., config: _Optional[_Union[McpConfig, _Mapping]] = ..., last_used_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., updated_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., url: _Optional[str] = ...) -> None: ... class McpConfig(_message.Message): - __slots__ = ("id", "name", "description", "connection_tool_mappings") + __slots__ = ("id", "name", "description", "connection_tool_mappings", "mcp_server_url") ID_FIELD_NUMBER: _ClassVar[int] NAME_FIELD_NUMBER: _ClassVar[int] DESCRIPTION_FIELD_NUMBER: _ClassVar[int] CONNECTION_TOOL_MAPPINGS_FIELD_NUMBER: _ClassVar[int] + MCP_SERVER_URL_FIELD_NUMBER: _ClassVar[int] id: str name: str description: str connection_tool_mappings: _containers.RepeatedCompositeFieldContainer[McpConfigConnectionToolMapping] - def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., connection_tool_mappings: _Optional[_Iterable[_Union[McpConfigConnectionToolMapping, _Mapping]]] = ...) -> None: ... + mcp_server_url: str + def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., connection_tool_mappings: _Optional[_Iterable[_Union[McpConfigConnectionToolMapping, _Mapping]]] = ..., mcp_server_url: _Optional[str] = ...) -> None: ... class McpConfigConnectionToolMapping(_message.Message): __slots__ = ("connection_id", "connection_name", "provider", "tools", "connected_account_id", "connected_account_status") @@ -337,3 +374,21 @@ class McpConfigConnectionToolMapping(_message.Message): connected_account_id: str connected_account_status: str def __init__(self, connection_id: _Optional[str] = ..., connection_name: _Optional[str] = ..., provider: _Optional[str] = ..., tools: _Optional[_Iterable[str]] = ..., connected_account_id: _Optional[str] = ..., connected_account_status: _Optional[str] = ...) -> None: ... + +class CreateMcpSessionTokenRequest(_message.Message): + __slots__ = ("mcp_config_id", "identifier", "expiry") + MCP_CONFIG_ID_FIELD_NUMBER: _ClassVar[int] + IDENTIFIER_FIELD_NUMBER: _ClassVar[int] + EXPIRY_FIELD_NUMBER: _ClassVar[int] + mcp_config_id: str + identifier: str + expiry: _duration_pb2.Duration + def __init__(self, mcp_config_id: _Optional[str] = ..., identifier: _Optional[str] = ..., expiry: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ...) -> None: ... + +class CreateMcpSessionTokenResponse(_message.Message): + __slots__ = ("token", "expires_at") + TOKEN_FIELD_NUMBER: _ClassVar[int] + EXPIRES_AT_FIELD_NUMBER: _ClassVar[int] + token: str + expires_at: _timestamp_pb2.Timestamp + def __init__(self, token: _Optional[str] = ..., expires_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... diff --git a/scalekit/v1/mcp/mcp_pb2_grpc.py b/scalekit/v1/mcp/mcp_pb2_grpc.py index 99fc2cd..3f14fd0 100644 --- a/scalekit/v1/mcp/mcp_pb2_grpc.py +++ b/scalekit/v1/mcp/mcp_pb2_grpc.py @@ -89,6 +89,16 @@ def __init__(self, channel): request_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.GetMcpInstanceAuthStateRequest.SerializeToString, response_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.GetMcpInstanceAuthStateResponse.FromString, ) + self.CreateMcpSessionToken = channel.unary_unary( + '/scalekit.v1.mcp.McpService/CreateMcpSessionToken', + request_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenRequest.SerializeToString, + response_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenResponse.FromString, + ) + self.ListMcpConnectedAccounts = channel.unary_unary( + '/scalekit.v1.mcp.McpService/ListMcpConnectedAccounts', + request_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsRequest.SerializeToString, + response_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsResponse.FromString, + ) class McpServiceServicer(object): @@ -184,6 +194,18 @@ def GetMcpInstanceAuthState(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def CreateMcpSessionToken(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListMcpConnectedAccounts(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_McpServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -262,6 +284,16 @@ def add_McpServiceServicer_to_server(servicer, server): request_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.GetMcpInstanceAuthStateRequest.FromString, response_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.GetMcpInstanceAuthStateResponse.SerializeToString, ), + 'CreateMcpSessionToken': grpc.unary_unary_rpc_method_handler( + servicer.CreateMcpSessionToken, + request_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenRequest.FromString, + response_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenResponse.SerializeToString, + ), + 'ListMcpConnectedAccounts': grpc.unary_unary_rpc_method_handler( + servicer.ListMcpConnectedAccounts, + request_deserializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsRequest.FromString, + response_serializer=scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( 'scalekit.v1.mcp.McpService', rpc_method_handlers) @@ -526,3 +558,37 @@ def GetMcpInstanceAuthState(request, scalekit_dot_v1_dot_mcp_dot_mcp__pb2.GetMcpInstanceAuthStateResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def CreateMcpSessionToken(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/scalekit.v1.mcp.McpService/CreateMcpSessionToken', + scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenRequest.SerializeToString, + scalekit_dot_v1_dot_mcp_dot_mcp__pb2.CreateMcpSessionTokenResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def ListMcpConnectedAccounts(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/scalekit.v1.mcp.McpService/ListMcpConnectedAccounts', + scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsRequest.SerializeToString, + scalekit_dot_v1_dot_mcp_dot_mcp__pb2.ListMcpConnectedAccountsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/scalekit/v1/migrations/migrations_pb2.py b/scalekit/v1/migrations/migrations_pb2.py index 9eadb56..a88278b 100644 --- a/scalekit/v1/migrations/migrations_pb2.py +++ b/scalekit/v1/migrations/migrations_pb2.py @@ -14,6 +14,7 @@ from buf.validate import validate_pb2 as buf_dot_validate_dot_validate__pb2 from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 +from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 from google.api import visibility_pb2 as google_dot_api_dot_visibility__pb2 from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 from protoc_gen_openapiv2.options import annotations_pb2 as protoc__gen__openapiv2_dot_options_dot_annotations__pb2 @@ -21,7 +22,7 @@ from scalekit.v1.options import options_pb2 as scalekit_dot_v1_dot_options_dot_options__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'scalekit/v1/migrations/migrations.proto\x12\x16scalekit.v1.migrations\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a!scalekit/v1/commons/commons.proto\x1a!scalekit/v1/options/options.proto\"@\n\x15MigrateEnvKeysRequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\tR\x0e\x65nvironmentIds\"O\n\x16MigrateEnvKeysResponse\x12\x35\n\x16\x65nvironments_processed\x18\x01 \x01(\x05R\x15\x65nvironmentsProcessed\"~\n\x18MigrationServiceResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"f\n\x14MigrationSAMLRequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\x03R\x0e\x65nvironmentIds\x12%\n\nbatch_size\x18\x02 \x01(\x05\x42\x06\xbaH\x03\xc8\x01\x01R\tbatchSize\"\xad\x01\n\x11MigrateFSARequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\x03R\x0e\x65nvironmentIds\x12H\n\tdata_type\x18\x02 \x01(\x0e\x32#.scalekit.v1.migrations.FSADataTypeB\x06\xbaH\x03\xc8\x01\x01R\x08\x64\x61taType\x12%\n\nbatch_size\x18\x03 \x01(\x05\x42\x06\xbaH\x03\xc8\x01\x01R\tbatchSize\"z\n\x14MigrationFSAResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"\x91\x01\n\x1dMigrateStripeCustomersRequest\x12p\n\x18migrate_stripe_customers\x18\x01 \x01(\x0b\x32..scalekit.v1.migrations.MigrateStripeCustomersB\x06\xbaH\x03\xc8\x01\x01R\x16migrateStripeCustomers\"\xad\x01\n\x16MigrateStripeCustomers\x12#\n\rworkspace_ids\x18\x01 \x03(\x03R\x0cworkspaceIds\x12\x1b\n\tplan_name\x18\x02 \x01(\tR\x08planName\x12\x1d\n\nbatch_size\x18\x03 \x01(\x05R\tbatchSize\x12\x32\n\x15include_test_accounts\x18\x04 \x01(\x08R\x13includeTestAccounts\"\xc1\x01\n\x1eMigrateStripeCustomersResponse\x12#\n\rsuccess_count\x18\x01 \x01(\x05R\x0csuccessCount\x12!\n\x0c\x66\x61iled_count\x18\x02 \x01(\x05R\x0b\x66\x61iledCount\x12\x30\n\x14\x66\x61iled_workspace_ids\x18\x03 \x03(\x03R\x12\x66\x61iledWorkspaceIds\x12%\n\x0e\x65rror_messages\x18\x04 \x03(\tR\rerrorMessages\"{\n\x15MigrationSAMLResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"\x96\x02\n\x1aMigrateWorkspaceFGARequest\x12#\n\rworkspace_ids\x18\x01 \x03(\x03R\x0cworkspaceIds\x12\x14\n\x05\x61sync\x18\x02 \x01(\x08R\x05\x61sync\x12)\n\x10organization_ids\x18\x03 \x03(\x03R\x0forganizationIds\x12#\n\rdirectory_ids\x18\x04 \x03(\x03R\x0c\x64irectoryIds\x12%\n\x0e\x63onnection_ids\x18\x05 \x03(\x03R\rconnectionIds\x12\x1d\n\nclient_ids\x18\x06 \x03(\x03R\tclientIds\x12\'\n\x0f\x65nvironment_ids\x18\x07 \x03(\x03R\x0e\x65nvironmentIds\"2\n\x0ePermissionList\x12 \n\x0bpermissions\x18\x01 \x03(\tR\x0bpermissions\"\xbb\x02\n\x1dMigrateRolePermissionsRequest\x12}\n\x10role_permissions\x18\x01 \x03(\x0b\x32J.scalekit.v1.migrations.MigrateRolePermissionsRequest.RolePermissionsEntryB\x06\xbaH\x03\xc8\x01\x01R\x0frolePermissions\x12/\n\x0f\x65nvironment_ids\x18\x02 \x03(\x03\x42\x06\xbaH\x03\xc8\x01\x01R\x0e\x65nvironmentIds\x1aj\n\x14RolePermissionsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12<\n\x05value\x18\x02 \x01(\x0b\x32&.scalekit.v1.migrations.PermissionListR\x05value:\x02\x38\x01\"\xca\x02\n\x1eMigrateRolePermissionsResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\x12%\n\x0e\x65rror_messages\x18\x03 \x03(\tR\rerrorMessages\x12#\n\rroles_created\x18\x04 \x01(\x05R\x0crolesCreated\x12/\n\x13permissions_created\x18\x05 \x01(\x05R\x12permissionsCreated\x12G\n role_permission_mappings_created\x18\x06 \x01(\x05R\x1drolePermissionMappingsCreated*\x88\x01\n\x0b\x46SADataType\x12\x1d\n\x19\x46SA_DATA_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x46SA_DATA_TYPE_CONNECTION\x10\x01\x12\x19\n\x15\x46SA_DATA_TYPE_SESSION\x10\x02\x12!\n\x1d\x46SA_DATA_TYPE_USER_MANAGEMENT\x10\x03\x32\x8f\n\n\x10MigrationService\x12\x9c\x01\n\x0eMigrateFSAData\x12).scalekit.v1.migrations.MigrateFSARequest\x1a,.scalekit.v1.migrations.MigrationFSAResponse\"1\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x16\"\x14/migrations/fsa-data\x12\xdc\x01\n\x16MigrateStripeCustomers\x12\x35.scalekit.v1.migrations.MigrateStripeCustomersRequest\x1a\x36.scalekit.v1.migrations.MigrateStripeCustomersResponse\"S\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x38\"\x1c/migrations/stripe-customers:\x18migrate_stripe_customers\x12\x9c\x01\n\x13MigrateWorkspaceFGA\x12\x32.scalekit.v1.migrations.MigrateWorkspaceFGARequest\x1a\x16.google.protobuf.Empty\"9\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x1e\"\x19/migrations/workspace-fga:\x01*\x12\xc5\x01\n\x16MigrateRolePermissions\x12\x35.scalekit.v1.migrations.MigrateRolePermissionsRequest\x1a\x36.scalekit.v1.migrations.MigrateRolePermissionsResponse\"<\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02!\"\x1c/migrations/role-permissions:\x01*\x12\x95\x04\n\x0eMigrateEnvKeys\x12-.scalekit.v1.migrations.MigrateEnvKeysRequest\x1a..scalekit.v1.migrations.MigrateEnvKeysResponse\"\xa3\x03\x92\x41\xeb\x02\n\x0eKey Management\x12&Ensure DEKs for specified environments\x1a\xb0\x02\x45nsures each listed environment has at least one active DEK. Only callable from the Scalekit platform environment. Provide environment_ids (e.g. env_123) in the request. Creates a DEK only for environments that do not have one (idempotent per environment). Use to backfill DEKs for specific environments.\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x19\"\x14/migrations/env-keys:\x01*B6Z4github.com/scalekit-inc/scalekit/pkg/grpc/migrationsb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'scalekit/v1/migrations/migrations.proto\x12\x16scalekit.v1.migrations\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/api/visibility.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a!scalekit/v1/commons/commons.proto\x1a!scalekit/v1/options/options.proto\"@\n\x15MigrateEnvKeysRequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\tR\x0e\x65nvironmentIds\"O\n\x16MigrateEnvKeysResponse\x12\x35\n\x16\x65nvironments_processed\x18\x01 \x01(\x05R\x15\x65nvironmentsProcessed\"~\n\x18MigrationServiceResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"f\n\x14MigrationSAMLRequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\x03R\x0e\x65nvironmentIds\x12%\n\nbatch_size\x18\x02 \x01(\x05\x42\x06\xbaH\x03\xc8\x01\x01R\tbatchSize\"\xad\x01\n\x11MigrateFSARequest\x12\'\n\x0f\x65nvironment_ids\x18\x01 \x03(\x03R\x0e\x65nvironmentIds\x12H\n\tdata_type\x18\x02 \x01(\x0e\x32#.scalekit.v1.migrations.FSADataTypeB\x06\xbaH\x03\xc8\x01\x01R\x08\x64\x61taType\x12%\n\nbatch_size\x18\x03 \x01(\x05\x42\x06\xbaH\x03\xc8\x01\x01R\tbatchSize\"z\n\x14MigrationFSAResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"\x91\x01\n\x1dMigrateStripeCustomersRequest\x12p\n\x18migrate_stripe_customers\x18\x01 \x01(\x0b\x32..scalekit.v1.migrations.MigrateStripeCustomersB\x06\xbaH\x03\xc8\x01\x01R\x16migrateStripeCustomers\"\xad\x01\n\x16MigrateStripeCustomers\x12#\n\rworkspace_ids\x18\x01 \x03(\x03R\x0cworkspaceIds\x12\x1b\n\tplan_name\x18\x02 \x01(\tR\x08planName\x12\x1d\n\nbatch_size\x18\x03 \x01(\x05R\tbatchSize\x12\x32\n\x15include_test_accounts\x18\x04 \x01(\x08R\x13includeTestAccounts\"\xc1\x01\n\x1eMigrateStripeCustomersResponse\x12#\n\rsuccess_count\x18\x01 \x01(\x05R\x0csuccessCount\x12!\n\x0c\x66\x61iled_count\x18\x02 \x01(\x05R\x0b\x66\x61iledCount\x12\x30\n\x14\x66\x61iled_workspace_ids\x18\x03 \x03(\x03R\x12\x66\x61iledWorkspaceIds\x12%\n\x0e\x65rror_messages\x18\x04 \x03(\tR\rerrorMessages\"{\n\x15MigrationSAMLResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\"\x96\x02\n\x1aMigrateWorkspaceFGARequest\x12#\n\rworkspace_ids\x18\x01 \x03(\x03R\x0cworkspaceIds\x12\x14\n\x05\x61sync\x18\x02 \x01(\x08R\x05\x61sync\x12)\n\x10organization_ids\x18\x03 \x03(\x03R\x0forganizationIds\x12#\n\rdirectory_ids\x18\x04 \x03(\x03R\x0c\x64irectoryIds\x12%\n\x0e\x63onnection_ids\x18\x05 \x03(\x03R\rconnectionIds\x12\x1d\n\nclient_ids\x18\x06 \x03(\x03R\tclientIds\x12\'\n\x0f\x65nvironment_ids\x18\x07 \x03(\x03R\x0e\x65nvironmentIds\"2\n\x0ePermissionList\x12 \n\x0bpermissions\x18\x01 \x03(\tR\x0bpermissions\"\xbb\x02\n\x1dMigrateRolePermissionsRequest\x12}\n\x10role_permissions\x18\x01 \x03(\x0b\x32J.scalekit.v1.migrations.MigrateRolePermissionsRequest.RolePermissionsEntryB\x06\xbaH\x03\xc8\x01\x01R\x0frolePermissions\x12/\n\x0f\x65nvironment_ids\x18\x02 \x03(\x03\x42\x06\xbaH\x03\xc8\x01\x01R\x0e\x65nvironmentIds\x1aj\n\x14RolePermissionsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12<\n\x05value\x18\x02 \x01(\x0b\x32&.scalekit.v1.migrations.PermissionListR\x05value:\x02\x38\x01\"\xca\x02\n\x1eMigrateRolePermissionsResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\x12%\n\x0e\x65rror_messages\x18\x03 \x03(\tR\rerrorMessages\x12#\n\rroles_created\x18\x04 \x01(\x05R\x0crolesCreated\x12/\n\x13permissions_created\x18\x05 \x01(\x05R\x12permissionsCreated\x12G\n role_permission_mappings_created\x18\x06 \x01(\x05R\x1drolePermissionMappingsCreated\"\x87\x01\n$MigrateEnvironmentPermissionsRequest\x12\x32\n\x0f\x65nvironment_ids\x18\x01 \x03(\x03\x42\t\xe0\x41\x02\xbaH\x03\xc8\x01\x01R\x0e\x65nvironmentIds\x12+\n\x0bpermissions\x18\x02 \x03(\tB\t\xe0\x41\x02\xbaH\x03\xc8\x01\x01R\x0bpermissions\"\xe3\x01\n%MigrateEnvironmentPermissionsResponse\x12\x31\n\x14success_environments\x18\x01 \x01(\x05R\x13successEnvironments\x12/\n\x13\x66\x61iled_environments\x18\x02 \x01(\x05R\x12\x66\x61iledEnvironments\x12%\n\x0e\x65rror_messages\x18\x03 \x03(\tR\rerrorMessages\x12/\n\x13permissions_created\x18\x04 \x01(\x05R\x12permissionsCreated*\x88\x01\n\x0b\x46SADataType\x12\x1d\n\x19\x46SA_DATA_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x46SA_DATA_TYPE_CONNECTION\x10\x01\x12\x19\n\x15\x46SA_DATA_TYPE_SESSION\x10\x02\x12!\n\x1d\x46SA_DATA_TYPE_USER_MANAGEMENT\x10\x03\x32\xb8\x11\n\x10MigrationService\x12\x9c\x01\n\x0eMigrateFSAData\x12).scalekit.v1.migrations.MigrateFSARequest\x1a,.scalekit.v1.migrations.MigrationFSAResponse\"1\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x16\"\x14/migrations/fsa-data\x12\xdc\x01\n\x16MigrateStripeCustomers\x12\x35.scalekit.v1.migrations.MigrateStripeCustomersRequest\x1a\x36.scalekit.v1.migrations.MigrateStripeCustomersResponse\"S\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x38\"\x1c/migrations/stripe-customers:\x18migrate_stripe_customers\x12\x9c\x01\n\x13MigrateWorkspaceFGA\x12\x32.scalekit.v1.migrations.MigrateWorkspaceFGARequest\x1a\x16.google.protobuf.Empty\"9\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x1e\"\x19/migrations/workspace-fga:\x01*\x12\xc5\x01\n\x16MigrateRolePermissions\x12\x35.scalekit.v1.migrations.MigrateRolePermissionsRequest\x1a\x36.scalekit.v1.migrations.MigrateRolePermissionsResponse\"<\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02!\"\x1c/migrations/role-permissions:\x01*\x12\xa6\x07\n\x1dMigrateEnvironmentPermissions\x12<.scalekit.v1.migrations.MigrateEnvironmentPermissionsRequest\x1a=.scalekit.v1.migrations.MigrateEnvironmentPermissionsResponse\"\x87\x06\x92\x41\xc0\x05\n\nMigrations\x12\"Create permissions in environments\x1a\xd8\x02\x43reates platform-defined permissions in each listed environment without attaching them to any role or writing to FGA. Validates all permission names against the platform permission registry before writing. Idempotent \xe2\x80\x94 existing permissions are skipped. A failure in one environment does not abort others; results are reported per environment.J\xb3\x01\n\x03\x32\x30\x30\x12\xab\x01\nfMigration completed; includes per-environment success and failure counts and total permissions created\x12\x41\n?\x1a=.scalekit.v1.migrations.MigrateEnvironmentPermissionsResponseJ}\n\x03\x34\x30\x30\x12v\ntInvalid request \xe2\x80\x94 environment_ids or permissions is empty, or a permission name is not a valid platform permission\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02(\"#/migrations/environment-permissions:\x01*\x12\x95\x04\n\x0eMigrateEnvKeys\x12-.scalekit.v1.migrations.MigrateEnvKeysRequest\x1a..scalekit.v1.migrations.MigrateEnvKeysResponse\"\xa3\x03\x92\x41\xeb\x02\n\x0eKey Management\x12&Ensure DEKs for specified environments\x1a\xb0\x02\x45nsures each listed environment has at least one active DEK. Only callable from the Scalekit platform environment. Provide environment_ids (e.g. env_123) in the request. Creates a DEK only for environments that do not have one (idempotent per environment). Use to backfill DEKs for specific environments.\x82\xb5\x18\x02\x18\x01\xfa\xd2\xe4\x93\x02\t\x12\x07PREVIEW\x82\xd3\xe4\x93\x02\x19\"\x14/migrations/env-keys:\x01*B6Z4github.com/scalekit-inc/scalekit/pkg/grpc/migrationsb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -43,6 +44,10 @@ _globals['_MIGRATEROLEPERMISSIONSREQUEST'].fields_by_name['role_permissions']._serialized_options = b'\272H\003\310\001\001' _globals['_MIGRATEROLEPERMISSIONSREQUEST'].fields_by_name['environment_ids']._loaded_options = None _globals['_MIGRATEROLEPERMISSIONSREQUEST'].fields_by_name['environment_ids']._serialized_options = b'\272H\003\310\001\001' + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST'].fields_by_name['environment_ids']._loaded_options = None + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST'].fields_by_name['environment_ids']._serialized_options = b'\340A\002\272H\003\310\001\001' + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST'].fields_by_name['permissions']._loaded_options = None + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST'].fields_by_name['permissions']._serialized_options = b'\340A\002\272H\003\310\001\001' _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateFSAData']._loaded_options = None _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateFSAData']._serialized_options = b'\202\265\030\002\030\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002\026\"\024/migrations/fsa-data' _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateStripeCustomers']._loaded_options = None @@ -51,40 +56,46 @@ _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateWorkspaceFGA']._serialized_options = b'\202\265\030\002\030\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002\036\"\031/migrations/workspace-fga:\001*' _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateRolePermissions']._loaded_options = None _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateRolePermissions']._serialized_options = b'\202\265\030\002\030\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002!\"\034/migrations/role-permissions:\001*' + _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateEnvironmentPermissions']._loaded_options = None + _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateEnvironmentPermissions']._serialized_options = b'\222A\300\005\n\nMigrations\022\"Create permissions in environments\032\330\002Creates platform-defined permissions in each listed environment without attaching them to any role or writing to FGA. Validates all permission names against the platform permission registry before writing. Idempotent \342\200\224 existing permissions are skipped. A failure in one environment does not abort others; results are reported per environment.J\263\001\n\003200\022\253\001\nfMigration completed; includes per-environment success and failure counts and total permissions created\022A\n?\032=.scalekit.v1.migrations.MigrateEnvironmentPermissionsResponseJ}\n\003400\022v\ntInvalid request \342\200\224 environment_ids or permissions is empty, or a permission name is not a valid platform permission\202\265\030\002\030\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002(\"#/migrations/environment-permissions:\001*' _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateEnvKeys']._loaded_options = None _globals['_MIGRATIONSERVICE'].methods_by_name['MigrateEnvKeys']._serialized_options = b'\222A\353\002\n\016Key Management\022&Ensure DEKs for specified environments\032\260\002Ensures each listed environment has at least one active DEK. Only callable from the Scalekit platform environment. Provide environment_ids (e.g. env_123) in the request. Creates a DEK only for environments that do not have one (idempotent per environment). Use to backfill DEKs for specific environments.\202\265\030\002\030\001\372\322\344\223\002\t\022\007PREVIEW\202\323\344\223\002\031\"\024/migrations/env-keys:\001*' - _globals['_FSADATATYPE']._serialized_start=2611 - _globals['_FSADATATYPE']._serialized_end=2747 - _globals['_MIGRATEENVKEYSREQUEST']._serialized_start=302 - _globals['_MIGRATEENVKEYSREQUEST']._serialized_end=366 - _globals['_MIGRATEENVKEYSRESPONSE']._serialized_start=368 - _globals['_MIGRATEENVKEYSRESPONSE']._serialized_end=447 - _globals['_MIGRATIONSERVICERESPONSE']._serialized_start=449 - _globals['_MIGRATIONSERVICERESPONSE']._serialized_end=575 - _globals['_MIGRATIONSAMLREQUEST']._serialized_start=577 - _globals['_MIGRATIONSAMLREQUEST']._serialized_end=679 - _globals['_MIGRATEFSAREQUEST']._serialized_start=682 - _globals['_MIGRATEFSAREQUEST']._serialized_end=855 - _globals['_MIGRATIONFSARESPONSE']._serialized_start=857 - _globals['_MIGRATIONFSARESPONSE']._serialized_end=979 - _globals['_MIGRATESTRIPECUSTOMERSREQUEST']._serialized_start=982 - _globals['_MIGRATESTRIPECUSTOMERSREQUEST']._serialized_end=1127 - _globals['_MIGRATESTRIPECUSTOMERS']._serialized_start=1130 - _globals['_MIGRATESTRIPECUSTOMERS']._serialized_end=1303 - _globals['_MIGRATESTRIPECUSTOMERSRESPONSE']._serialized_start=1306 - _globals['_MIGRATESTRIPECUSTOMERSRESPONSE']._serialized_end=1499 - _globals['_MIGRATIONSAMLRESPONSE']._serialized_start=1501 - _globals['_MIGRATIONSAMLRESPONSE']._serialized_end=1624 - _globals['_MIGRATEWORKSPACEFGAREQUEST']._serialized_start=1627 - _globals['_MIGRATEWORKSPACEFGAREQUEST']._serialized_end=1905 - _globals['_PERMISSIONLIST']._serialized_start=1907 - _globals['_PERMISSIONLIST']._serialized_end=1957 - _globals['_MIGRATEROLEPERMISSIONSREQUEST']._serialized_start=1960 - _globals['_MIGRATEROLEPERMISSIONSREQUEST']._serialized_end=2275 - _globals['_MIGRATEROLEPERMISSIONSREQUEST_ROLEPERMISSIONSENTRY']._serialized_start=2169 - _globals['_MIGRATEROLEPERMISSIONSREQUEST_ROLEPERMISSIONSENTRY']._serialized_end=2275 - _globals['_MIGRATEROLEPERMISSIONSRESPONSE']._serialized_start=2278 - _globals['_MIGRATEROLEPERMISSIONSRESPONSE']._serialized_end=2608 - _globals['_MIGRATIONSERVICE']._serialized_start=2750 - _globals['_MIGRATIONSERVICE']._serialized_end=4045 + _globals['_FSADATATYPE']._serialized_start=3012 + _globals['_FSADATATYPE']._serialized_end=3148 + _globals['_MIGRATEENVKEYSREQUEST']._serialized_start=335 + _globals['_MIGRATEENVKEYSREQUEST']._serialized_end=399 + _globals['_MIGRATEENVKEYSRESPONSE']._serialized_start=401 + _globals['_MIGRATEENVKEYSRESPONSE']._serialized_end=480 + _globals['_MIGRATIONSERVICERESPONSE']._serialized_start=482 + _globals['_MIGRATIONSERVICERESPONSE']._serialized_end=608 + _globals['_MIGRATIONSAMLREQUEST']._serialized_start=610 + _globals['_MIGRATIONSAMLREQUEST']._serialized_end=712 + _globals['_MIGRATEFSAREQUEST']._serialized_start=715 + _globals['_MIGRATEFSAREQUEST']._serialized_end=888 + _globals['_MIGRATIONFSARESPONSE']._serialized_start=890 + _globals['_MIGRATIONFSARESPONSE']._serialized_end=1012 + _globals['_MIGRATESTRIPECUSTOMERSREQUEST']._serialized_start=1015 + _globals['_MIGRATESTRIPECUSTOMERSREQUEST']._serialized_end=1160 + _globals['_MIGRATESTRIPECUSTOMERS']._serialized_start=1163 + _globals['_MIGRATESTRIPECUSTOMERS']._serialized_end=1336 + _globals['_MIGRATESTRIPECUSTOMERSRESPONSE']._serialized_start=1339 + _globals['_MIGRATESTRIPECUSTOMERSRESPONSE']._serialized_end=1532 + _globals['_MIGRATIONSAMLRESPONSE']._serialized_start=1534 + _globals['_MIGRATIONSAMLRESPONSE']._serialized_end=1657 + _globals['_MIGRATEWORKSPACEFGAREQUEST']._serialized_start=1660 + _globals['_MIGRATEWORKSPACEFGAREQUEST']._serialized_end=1938 + _globals['_PERMISSIONLIST']._serialized_start=1940 + _globals['_PERMISSIONLIST']._serialized_end=1990 + _globals['_MIGRATEROLEPERMISSIONSREQUEST']._serialized_start=1993 + _globals['_MIGRATEROLEPERMISSIONSREQUEST']._serialized_end=2308 + _globals['_MIGRATEROLEPERMISSIONSREQUEST_ROLEPERMISSIONSENTRY']._serialized_start=2202 + _globals['_MIGRATEROLEPERMISSIONSREQUEST_ROLEPERMISSIONSENTRY']._serialized_end=2308 + _globals['_MIGRATEROLEPERMISSIONSRESPONSE']._serialized_start=2311 + _globals['_MIGRATEROLEPERMISSIONSRESPONSE']._serialized_end=2641 + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST']._serialized_start=2644 + _globals['_MIGRATEENVIRONMENTPERMISSIONSREQUEST']._serialized_end=2779 + _globals['_MIGRATEENVIRONMENTPERMISSIONSRESPONSE']._serialized_start=2782 + _globals['_MIGRATEENVIRONMENTPERMISSIONSRESPONSE']._serialized_end=3009 + _globals['_MIGRATIONSERVICE']._serialized_start=3151 + _globals['_MIGRATIONSERVICE']._serialized_end=5383 # @@protoc_insertion_point(module_scope) diff --git a/scalekit/v1/migrations/migrations_pb2.pyi b/scalekit/v1/migrations/migrations_pb2.pyi index 720a665..cc31847 100644 --- a/scalekit/v1/migrations/migrations_pb2.pyi +++ b/scalekit/v1/migrations/migrations_pb2.pyi @@ -1,5 +1,6 @@ from buf.validate import validate_pb2 as _validate_pb2 from google.api import annotations_pb2 as _annotations_pb2 +from google.api import field_behavior_pb2 as _field_behavior_pb2 from google.api import visibility_pb2 as _visibility_pb2 from google.protobuf import empty_pb2 as _empty_pb2 from protoc_gen_openapiv2.options import annotations_pb2 as _annotations_pb2_1 @@ -161,3 +162,23 @@ class MigrateRolePermissionsResponse(_message.Message): permissions_created: int role_permission_mappings_created: int def __init__(self, success_environments: _Optional[int] = ..., failed_environments: _Optional[int] = ..., error_messages: _Optional[_Iterable[str]] = ..., roles_created: _Optional[int] = ..., permissions_created: _Optional[int] = ..., role_permission_mappings_created: _Optional[int] = ...) -> None: ... + +class MigrateEnvironmentPermissionsRequest(_message.Message): + __slots__ = ("environment_ids", "permissions") + ENVIRONMENT_IDS_FIELD_NUMBER: _ClassVar[int] + PERMISSIONS_FIELD_NUMBER: _ClassVar[int] + environment_ids: _containers.RepeatedScalarFieldContainer[int] + permissions: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, environment_ids: _Optional[_Iterable[int]] = ..., permissions: _Optional[_Iterable[str]] = ...) -> None: ... + +class MigrateEnvironmentPermissionsResponse(_message.Message): + __slots__ = ("success_environments", "failed_environments", "error_messages", "permissions_created") + SUCCESS_ENVIRONMENTS_FIELD_NUMBER: _ClassVar[int] + FAILED_ENVIRONMENTS_FIELD_NUMBER: _ClassVar[int] + ERROR_MESSAGES_FIELD_NUMBER: _ClassVar[int] + PERMISSIONS_CREATED_FIELD_NUMBER: _ClassVar[int] + success_environments: int + failed_environments: int + error_messages: _containers.RepeatedScalarFieldContainer[str] + permissions_created: int + def __init__(self, success_environments: _Optional[int] = ..., failed_environments: _Optional[int] = ..., error_messages: _Optional[_Iterable[str]] = ..., permissions_created: _Optional[int] = ...) -> None: ... diff --git a/scalekit/v1/migrations/migrations_pb2_grpc.py b/scalekit/v1/migrations/migrations_pb2_grpc.py index b039e15..680d40e 100644 --- a/scalekit/v1/migrations/migrations_pb2_grpc.py +++ b/scalekit/v1/migrations/migrations_pb2_grpc.py @@ -35,6 +35,11 @@ def __init__(self, channel): request_serializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateRolePermissionsRequest.SerializeToString, response_deserializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateRolePermissionsResponse.FromString, ) + self.MigrateEnvironmentPermissions = channel.unary_unary( + '/scalekit.v1.migrations.MigrationService/MigrateEnvironmentPermissions', + request_serializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsRequest.SerializeToString, + response_deserializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsResponse.FromString, + ) self.MigrateEnvKeys = channel.unary_unary( '/scalekit.v1.migrations.MigrationService/MigrateEnvKeys', request_serializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvKeysRequest.SerializeToString, @@ -69,6 +74,12 @@ def MigrateRolePermissions(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def MigrateEnvironmentPermissions(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def MigrateEnvKeys(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -98,6 +109,11 @@ def add_MigrationServiceServicer_to_server(servicer, server): request_deserializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateRolePermissionsRequest.FromString, response_serializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateRolePermissionsResponse.SerializeToString, ), + 'MigrateEnvironmentPermissions': grpc.unary_unary_rpc_method_handler( + servicer.MigrateEnvironmentPermissions, + request_deserializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsRequest.FromString, + response_serializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsResponse.SerializeToString, + ), 'MigrateEnvKeys': grpc.unary_unary_rpc_method_handler( servicer.MigrateEnvKeys, request_deserializer=scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvKeysRequest.FromString, @@ -181,6 +197,23 @@ def MigrateRolePermissions(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def MigrateEnvironmentPermissions(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/scalekit.v1.migrations.MigrationService/MigrateEnvironmentPermissions', + scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsRequest.SerializeToString, + scalekit_dot_v1_dot_migrations_dot_migrations__pb2.MigrateEnvironmentPermissionsResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def MigrateEnvKeys(request, target, diff --git a/tests/test_actions.py b/tests/test_actions.py index e1ca0f5..b234cdc 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -1,4 +1,5 @@ import unittest +from datetime import timedelta from basetest import BaseTest from scalekit.common.exceptions import ScalekitNotFoundException @@ -23,6 +24,8 @@ DeleteMcpInstanceResponse, GetMcpInstanceAuthStateResponse, VerifyConnectedAccountUserResponse, + ListMcpConnectedAccountsResponse, + CreateMcpSessionTokenResponse, ) from scalekit.actions.models.responses.get_connected_account_auth_response import ConnectedAccount from scalekit.actions.modifier import Modifier @@ -150,6 +153,24 @@ def test_list_connected_accounts_response_structure(self): except Exception as e: raise e + def test_list_connected_accounts_with_connection_names_filter(self): + """connection_names filter passes through the action layer and returns a valid response.""" + result = self.scalekit_client.actions.list_connected_accounts( + connection_names=[self.test_connection_name], + ) + self.assertIsNotNone(result) + self.assertIsInstance(result, ListConnectedAccountsResponse) + self.assertTrue(hasattr(result, 'connected_accounts')) + + def test_list_connected_accounts_connection_names_with_page_size(self): + """connection_names filter can be combined with pagination parameters.""" + result = self.scalekit_client.actions.list_connected_accounts( + connection_names=[self.test_connection_name], + page_size=5, + ) + self.assertIsNotNone(result) + self.assertIsInstance(result, ListConnectedAccountsResponse) + def test_magic_link_response_structure(self): """Method to test MagicLinkResponse structure and methods""" from datetime import datetime @@ -1535,6 +1556,46 @@ def test_actions_mcp_config_lifecycle(self): ) self.assertIsInstance(delete_response, DeleteMcpConfigResponse) + def test_list_configs_filter_by_mcp_server_url(self): + """list_configs(filter_mcp_server_url=...) returns only configs with that server URL.""" + import uuid + + config_name = f"py-test-url-filter-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.actions_client.mcp.create_config( + name=config_name, + description="mcp_server_url filter test", + connection_tool_mappings=[ + McpConfigConnectionToolMapping( + connection_name=self.seed_connection_name, + tools=self.seed_tools[:1], + ) + ], + ) + self.assertIsInstance(create_response, CreateMcpConfigResponse) + created_config_id = create_response.config.id + + # Retrieve the server-assigned mcp_server_url + by_id = self.actions_client.mcp.list_configs(filter_id=created_config_id) + self.assertIsInstance(by_id, ListMcpConfigsResponse) + self.assertTrue(by_id.configs) + + mcp_server_url = by_id.configs[0].mcp_server_url + if not mcp_server_url: + self.skipTest("Server did not assign mcp_server_url to this config") + + filtered = self.actions_client.mcp.list_configs( + filter_mcp_server_url=mcp_server_url + ) + self.assertIsInstance(filtered, ListMcpConfigsResponse) + self.assertIn(created_config_id, [c.id for c in filtered.configs]) + + finally: + if created_config_id: + self.actions_client.mcp.delete_config(config_id=created_config_id) + class TestActionsMcpInstance(BaseTest): """Tests for MCP instance lifecycle via the actions client.""" @@ -1655,6 +1716,134 @@ def test_actions_mcp_instance_auth_state_variants(self): self.assertIsInstance(delete_response, DeleteMcpInstanceResponse) +class TestActionsMcpConnectedAccounts(BaseTest): + """Tests for list_mcp_connected_accounts and create_session_token via the actions client. + + Uses a fixed test identifier (john-doe-sdk-test) that has MY_CALENDAR connected. + A fresh MCP config is created in setUp and deleted in tearDown so every test + gets a clean slate without duplicating create/delete boilerplate. + """ + + MCP_CONNECTION_NAME = "MY_CALENDAR" + MCP_TOOLS = ["googlecalendar_create_event", "googlecalendar_delete_event"] + USER_IDENTIFIER = "john-doe-sdk-test" + + def setUp(self): + import uuid + self.actions_client = self.scalekit_client.actions + self.config_id = None # set before any call so tearDown can always guard on it + config_name = f"py-test-ca-{uuid.uuid4().hex[:8]}" + create_response = self.actions_client.mcp.create_config( + name=config_name, + description="Test config for connected account / session token tests", + connection_tool_mappings=[ + McpConfigConnectionToolMapping( + connection_name=self.MCP_CONNECTION_NAME, + tools=self.MCP_TOOLS, + ) + ], + ) + self.config_id = create_response.config.id # assign before asserting so tearDown can clean up + self.assertIsInstance(create_response, CreateMcpConfigResponse) + self.assertIsNotNone(self.config_id) + + def tearDown(self): + if getattr(self, 'config_id', None): + self.actions_client.mcp.delete_config(config_id=self.config_id) + + def test_list_mcp_connected_accounts(self): + """Returns one entry per connection; no auth link when include_auth_link is omitted.""" + result = self.actions_client.mcp.list_mcp_connected_accounts( + config_id=self.config_id, + identifier=self.USER_IDENTIFIER, + ) + self.assertIsInstance(result, ListMcpConnectedAccountsResponse) + self.assertTrue(hasattr(result, 'connected_accounts')) + # Config has exactly one connection (MY_CALENDAR) + self.assertEqual(len(result.connected_accounts), 1) + account = result.connected_accounts[0] + self.assertTrue(hasattr(account, 'connection_name')) + self.assertTrue(hasattr(account, 'connected_account_status')) + # Auth link should be absent when include_auth_link was not requested + self.assertFalse(account.authentication_link) + + def test_list_mcp_connected_accounts_with_auth_link(self): + """include_auth_link=True causes every connection to carry an authentication_link.""" + result = self.actions_client.mcp.list_mcp_connected_accounts( + config_id=self.config_id, + identifier=self.USER_IDENTIFIER, + include_auth_link=True, + ) + self.assertIsInstance(result, ListMcpConnectedAccountsResponse) + self.assertEqual(len(result.connected_accounts), 1) + for account in result.connected_accounts: + self.assertTrue( + account.authentication_link, + f"Expected authentication_link for {account.connection_name} when include_auth_link=True", + ) + + def test_list_mcp_connected_accounts_without_auth_link(self): + """include_auth_link=False explicitly omits the authentication_link.""" + result = self.actions_client.mcp.list_mcp_connected_accounts( + config_id=self.config_id, + identifier=self.USER_IDENTIFIER, + include_auth_link=False, + ) + self.assertIsInstance(result, ListMcpConnectedAccountsResponse) + for account in result.connected_accounts: + self.assertFalse( + account.authentication_link, + f"Expected no authentication_link for {account.connection_name} when include_auth_link=False", + ) + + def test_list_mcp_connected_accounts_validation(self): + """Omitting config_id or identifier raises ValueError.""" + with self.assertRaises(ValueError): + self.actions_client.mcp.list_mcp_connected_accounts( + config_id="", + identifier=self.USER_IDENTIFIER, + ) + with self.assertRaises(ValueError): + self.actions_client.mcp.list_mcp_connected_accounts( + config_id=self.config_id, + identifier="", + ) + + def test_create_session_token(self): + """create_session_token returns a non-empty token string and an expiry timestamp.""" + result = self.actions_client.mcp.create_session_token( + mcp_config_id=self.config_id, + identifier=self.USER_IDENTIFIER, + ) + self.assertIsInstance(result, CreateMcpSessionTokenResponse) + self.assertTrue(result.token, "Expected a non-empty token string") + self.assertIsNotNone(result.expires_at) + + def test_create_session_token_with_custom_expiry(self): + """create_session_token accepts an explicit timedelta expiry.""" + result = self.actions_client.mcp.create_session_token( + mcp_config_id=self.config_id, + identifier=self.USER_IDENTIFIER, + expiry=timedelta(hours=2), + ) + self.assertIsInstance(result, CreateMcpSessionTokenResponse) + self.assertTrue(result.token, "Expected a non-empty token string") + self.assertIsNotNone(result.expires_at) + + def test_create_session_token_validation(self): + """Omitting mcp_config_id or identifier raises ValueError.""" + with self.assertRaises(ValueError): + self.actions_client.mcp.create_session_token( + mcp_config_id="", + identifier=self.USER_IDENTIFIER, + ) + with self.assertRaises(ValueError): + self.actions_client.mcp.create_session_token( + mcp_config_id=self.config_id, + identifier="", + ) + + class TestConnectUserVerify(BaseTest): """Tests for verify_connected_account_user via the actions client.""" diff --git a/tests/test_connected_accounts.py b/tests/test_connected_accounts.py index a675685..1e86635 100644 --- a/tests/test_connected_accounts.py +++ b/tests/test_connected_accounts.py @@ -47,6 +47,71 @@ def test_list_connected_accounts_with_filters(self): self.assertEqual(response[1].code().name, "OK") self.assertTrue(response[0] is not None) + def test_list_connected_accounts_with_connection_names_filter(self): + """connection_names is accepted by the server and the created account appears in results.""" + connected_account = self._create_oauth_connected_account() + filter_identifier = f"ca_filter_test_{self.faker.uuid4()}" + created = False + + try: + create_response = self.scalekit_client.connected_accounts.create_connected_account( + connector=self.test_connector, + identifier=filter_identifier, + connected_account=connected_account, + ) + self.assertEqual(create_response[1].code().name, "OK") + created = True + + response = self.scalekit_client.connected_accounts.list_connected_accounts( + connection_names=[self.test_connector], + page_size=20, + ) + self.assertEqual(response[1].code().name, "OK") + self.assertTrue(hasattr(response[0], 'connected_accounts')) + # The newly created account must appear in the results + identifiers = [a.identifier for a in response[0].connected_accounts] + self.assertIn(filter_identifier, identifiers) + finally: + if created: + self.scalekit_client.connected_accounts.delete_connected_account( + connector=self.test_connector, + identifier=filter_identifier, + ) + + def test_list_connected_accounts_with_connection_names_combined_with_identifier(self): + """connection_names combined with identifier narrows results to that specific account.""" + connected_account = self._create_oauth_connected_account() + combined_identifier = f"ca_combined_test_{self.faker.uuid4()}" + created = False + + try: + create_response = self.scalekit_client.connected_accounts.create_connected_account( + connector=self.test_connector, + identifier=combined_identifier, + connected_account=connected_account, + ) + self.assertEqual(create_response[1].code().name, "OK") + created = True + + response = self.scalekit_client.connected_accounts.list_connected_accounts( + connection_names=[self.test_connector], + identifier=combined_identifier, + page_size=10, + ) + self.assertEqual(response[1].code().name, "OK") + self.assertTrue(hasattr(response[0], 'connected_accounts')) + identifiers = [a.identifier for a in response[0].connected_accounts] + self.assertIn( + combined_identifier, identifiers, + "Account created with this identifier must appear when filtered by it", + ) + finally: + if created: + self.scalekit_client.connected_accounts.delete_connected_account( + connector=self.test_connector, + identifier=combined_identifier, + ) + def test_create_connected_account_with_oauth(self): """ Method to test create connected account with OAuth """ connected_account = self._create_oauth_connected_account() diff --git a/tests/test_mcp.py b/tests/test_mcp.py index d695156..2924526 100644 --- a/tests/test_mcp.py +++ b/tests/test_mcp.py @@ -1,4 +1,5 @@ import uuid +from datetime import datetime, timedelta, timezone from faker import Faker from basetest import BaseTest @@ -18,6 +19,7 @@ def setUp(self): """ """ self.faker = Faker() self.test_connected_account_identifier = "default" + self.test_user_identifier = "john-doe-sdk-test" def _create_test_mcp(self): """Helper method to create test MCP object""" @@ -154,3 +156,146 @@ def test_get_instance_auth_state_include_links_variants(self): if instance_id: self.scalekit_client.mcp.delete_instance(instance_id=instance_id) self.scalekit_client.mcp.delete_config(config_id=created_config_id) + + def test_list_configs_filter_by_mcp_server_url(self): + """list_configs(filter_mcp_server_url=...) should return the matching config.""" + mcp_config = self._create_test_mcp_config() + mcp_config.name = f"py-test-url-filter-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.scalekit_client.mcp.create_config(mcp_config=mcp_config) + self.assertEqual(create_response[1].code().name, "OK") + created_config_id = create_response[0].config.id + + # Retrieve the server-assigned mcp_server_url via filter_id + list_response = self.scalekit_client.mcp.list_configs(filter_id=created_config_id) + self.assertEqual(list_response[1].code().name, "OK") + self.assertTrue(list_response[0].configs) + + mcp_server_url = list_response[0].configs[0].mcp_server_url + if not mcp_server_url: + self.skipTest("Server did not assign mcp_server_url to this config") + + filtered_response = self.scalekit_client.mcp.list_configs( + filter_mcp_server_url=mcp_server_url + ) + self.assertEqual(filtered_response[1].code().name, "OK") + config_ids = [c.id for c in filtered_response[0].configs] + self.assertIn(created_config_id, config_ids) + finally: + if created_config_id: + self.scalekit_client.mcp.delete_config(config_id=created_config_id) + + def test_list_mcp_connected_accounts(self): + """list_mcp_connected_accounts returns one entry per connection, no auth link by default.""" + mcp_config = self._create_test_mcp_config() + mcp_config.name = f"py-test-connected-accts-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.scalekit_client.mcp.create_config(mcp_config=mcp_config) + self.assertEqual(create_response[1].code().name, "OK") + created_config_id = create_response[0].config.id + + response = self.scalekit_client.mcp.list_mcp_connected_accounts( + config_id=created_config_id, + identifier=self.test_user_identifier, + ) + self.assertEqual(response[1].code().name, "OK") + self.assertTrue(hasattr(response[0], 'connected_accounts')) + # Config has one connection (MY_CALENDAR) so expect one entry + self.assertEqual(len(response[0].connected_accounts), 1) + account = response[0].connected_accounts[0] + self.assertTrue(hasattr(account, 'connection_name')) + self.assertTrue(hasattr(account, 'connected_account_status')) + # No auth link requested + self.assertFalse(account.authentication_link) + finally: + if created_config_id: + self.scalekit_client.mcp.delete_config(config_id=created_config_id) + + def test_list_mcp_connected_accounts_with_auth_link(self): + """include_auth_link=True causes every connection entry to carry an authentication_link.""" + mcp_config = self._create_test_mcp_config() + mcp_config.name = f"py-test-auth-link-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.scalekit_client.mcp.create_config(mcp_config=mcp_config) + self.assertEqual(create_response[1].code().name, "OK") + created_config_id = create_response[0].config.id + + response = self.scalekit_client.mcp.list_mcp_connected_accounts( + config_id=created_config_id, + identifier=self.test_user_identifier, + include_auth_link=True, + ) + self.assertEqual(response[1].code().name, "OK") + self.assertTrue(hasattr(response[0], 'connected_accounts')) + self.assertEqual(len(response[0].connected_accounts), 1) + for account in response[0].connected_accounts: + self.assertTrue( + account.authentication_link, + f"Expected authentication_link for {account.connection_name} when include_auth_link=True", + ) + finally: + if created_config_id: + self.scalekit_client.mcp.delete_config(config_id=created_config_id) + + def test_create_session_token(self): + """create_session_token returns a non-empty token and an expiry timestamp.""" + mcp_config = self._create_test_mcp_config() + mcp_config.name = f"py-test-session-token-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.scalekit_client.mcp.create_config(mcp_config=mcp_config) + self.assertEqual(create_response[1].code().name, "OK") + created_config_id = create_response[0].config.id + + token_response = self.scalekit_client.mcp.create_session_token( + mcp_config_id=created_config_id, + identifier=self.test_user_identifier, + ) + self.assertEqual(token_response[1].code().name, "OK") + self.assertTrue(token_response[0].token, "Expected a non-empty token string") + self.assertTrue(hasattr(token_response[0], 'expires_at')) + finally: + if created_config_id: + self.scalekit_client.mcp.delete_config(config_id=created_config_id) + + def test_create_session_token_with_custom_expiry(self): + """create_session_token respects an explicit expiry timedelta.""" + mcp_config = self._create_test_mcp_config() + mcp_config.name = f"py-test-session-expiry-{uuid.uuid4().hex[:8]}" + created_config_id = None + + try: + create_response = self.scalekit_client.mcp.create_config(mcp_config=mcp_config) + self.assertEqual(create_response[1].code().name, "OK") + created_config_id = create_response[0].config.id + + now = datetime.now(tz=timezone.utc) + token_response = self.scalekit_client.mcp.create_session_token( + mcp_config_id=created_config_id, + identifier=self.test_user_identifier, + expiry=timedelta(hours=2), + ) + self.assertEqual(token_response[1].code().name, "OK") + self.assertTrue(token_response[0].token, "Expected a non-empty token string") + self.assertTrue(hasattr(token_response[0], 'expires_at')) + expires_at = token_response[0].expires_at.ToDatetime(tzinfo=timezone.utc) + self.assertGreater( + expires_at, + now + timedelta(hours=1, minutes=55), + "expires_at should be at least 1h55m from now for a 2-hour expiry", + ) + self.assertLess( + expires_at, + now + timedelta(hours=2, minutes=5), + "expires_at should not exceed 2h5m from now for a 2-hour expiry", + ) + finally: + if created_config_id: + self.scalekit_client.mcp.delete_config(config_id=created_config_id)