{
  "resource": "https://laso.finance/",
  "resource_name": "Laso Finance",
  "authorization_servers": ["https://laso.finance"],
  "bearer_methods_supported": ["header"],

  "issuer": "https://laso.finance",
  "authorization_endpoint": "https://laso.finance/oauth/authorize",
  "token_endpoint": "https://laso.finance/oauth/token",
  "registration_endpoint": "https://laso.finance/oauth/register",
  "device_authorization_endpoint": "https://laso.finance/oauth/device_authorization",
  "revocation_endpoint": "https://laso.finance/oauth/revoke",
  "revocation_endpoint_auth_methods_supported": ["none"],
  "response_types_supported": ["code"],
  "grant_types_supported": [
    "authorization_code",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "scopes_supported": ["laso", "laso.account.read"],
  "client_id_metadata_document_supported": true,
  "service_documentation": "https://docs.laso.finance/guides/mcp-server",

  "agent_auth": {
    "skill": "https://laso.finance/auth.md",
    "register_uri": "https://laso.finance/auth",
    "claim_endpoint": "https://laso.finance/get-auth-link",
    "identity_types_supported": ["anonymous", "service_auth"],
    "credential_types_supported": ["id_token", "refresh_token", "api_key"],

    "registration_methods": [
      {
        "identity_type": "anonymous",
        "register_uri": "https://laso.finance/auth",
        "method": "GET",
        "presentation": "SIGN-IN-WITH-X header (base64-encoded CAIP-122 signed message)",
        "human_required": false,
        "description": "The agent proves control of a wallet keypair and receives credentials for the Laso account bound to that wallet. No human identity is asserted, and the account is created on first use. Base and Solana wallets are both accepted."
      },
      {
        "identity_type": "service_auth",
        "register_uri": "https://laso.finance/agentAuth",
        "method": "POST",
        "presentation": "Authorization: Bearer <api_key>",
        "human_required": true,
        "issuance_uri": "https://laso.finance/agent/dashboard",
        "description": "A human creates the account and issues the agent an api_key from the dashboard, then the agent exchanges that key for a session. Use this when the agent and a human share one Laso account."
      }
    ],

    "credentials": {
      "id_token": {
        "format": "jwt",
        "presentation": "Authorization: Bearer <id_token>",
        "expires_in": 3600,
        "renewal": "POST https://laso.finance/auth with grant_type=refresh_token"
      },
      "refresh_token": {
        "presentation": "JSON request body at POST https://laso.finance/auth",
        "grant_type": "refresh_token"
      },
      "api_key": {
        "prefix": "lasoak_",
        "presentation": "Authorization: Bearer <api_key>",
        "lifetime": "long-lived",
        "issuance_uri": "https://laso.finance/agent/dashboard",
        "issued_to": "human",
        "description": "Issued only with a human's approval: from the dashboard, by the signup claim link, or as the access token of an MCP client's OAuth connection (authorization_endpoint above). An agent cannot mint one for itself."
      },
      "account_read_token": {
        "format": "opaque",
        "scope": "laso.account.read",
        "resource": "https://laso.finance/mcp/account",
        "ttl_seconds": 2592000,
        "description": "Issued only through OAuth for read-only account access. Cannot be exchanged for a Firebase session or accepted by payment endpoints."
      }
    },

    "revocation": {
      "agent_callable": true,
      "endpoint": "https://laso.finance/oauth/revoke",
      "contact": "agents+support@laso.finance",
      "description": "An api_key is revoked by POSTing it as `token` to the RFC 7009 revocation_endpoint, by the revokeAgentApiKey callable, or by the account owner on the dashboard. A revoked key can no longer be exchanged for a session. A session already minted from it is not cut off: its id_token lasts out its hour and its refresh_token keeps working. An id_token cannot be revoked before its one-hour expiry. An account_read_token is revoked the same way, by POSTing it to the revocation_endpoint, and is refused from the next request on."
    },

    "human_verification": {
      "status_endpoint": "https://laso.finance/get-kyc-status",
      "link_endpoint": "https://laso.finance/get-kyc-link",
      "agent_completable": false,
      "description": "Optional and only required by some endpoints. The agent reads the requirement and hands the returned link to its human, who completes the form. Everything around it is agent-drivable."
    }
  }
}
