> ## Documentation Index
> Fetch the complete documentation index at: https://developers.datagrid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Complete MCP OAuth flow

> Complete an OAuth authorization flow for a registered MCP server by exchanging the authorization code returned from the OAuth provider. Requires a user-scoped API key (`dg_live_`); service keys (`dg_svc_`) are rejected with `mcp_oauth_requires_user_principal`.



## OpenAPI

````yaml post /organization/mcp-servers/{server_id}/oauth-callback
openapi: 3.0.3
info:
  version: 0.1.1
  title: Datagrid API
  description: Datagrid API
servers:
  - url: https://api.datagrid.com/v1
security:
  - BearerAuth: []
paths:
  /organization/mcp-servers/{server_id}/oauth-callback:
    post:
      tags:
        - MCP Servers
      summary: Complete MCP OAuth flow
      description: >-
        Complete an OAuth authorization flow for a registered MCP server by
        exchanging the authorization code returned from the OAuth provider.
        Requires a user-scoped API key (`dg_live_`); service keys (`dg_svc_`)
        are rejected with `mcp_oauth_requires_user_principal`.
      operationId: HandleMcpOAuthCallback
      parameters:
        - name: server_id
          in: path
          required: true
          schema:
            type: string
          description: The ID of the MCP server.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HandleMcpOAuthCallbackRequest'
      responses:
        '200':
          description: OAuth flow completed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HandleMcpOAuthCallbackResponse'
        '400':
          description: >-
            No pending OAuth flow was found, the flow expired, or the `state`
            parameter did not match the pending flow.
        '403':
          description: >-
            The API key cannot authorize a per-user OAuth flow (for example, a
            service key was used).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/McpOAuthRequiresUserPrincipalError'
        '404':
          description: MCP server not found
        '429':
          description: >-
            Rate limit exceeded. The request has been throttled because the rate
            limit for this endpoint has been reached. Check the `Retry-After`
            response header and retry after the specified number of seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
components:
  schemas:
    HandleMcpOAuthCallbackRequest:
      type: object
      required:
        - code
        - state
        - redirect_uri
      properties:
        code:
          type: string
          maxLength: 4096
          description: >-
            Authorization code returned by the OAuth authorization server on the
            callback.
        state:
          type: string
          maxLength: 512
          description: >-
            The `state` value the OAuth authorization server echoed on the
            callback. Must match the value returned from `start-oauth`.
        redirect_uri:
          type: string
          format: uri
          maxLength: 2048
          description: >-
            The same `redirect_uri` passed to `start-oauth`. HTTPS is required
            except for loopback (`http://localhost`, `http://127.0.0.1`,
            `http://[::1]`).
    HandleMcpOAuthCallbackResponse:
      type: object
      required:
        - object
        - oauth_configured
        - tools_synced
      properties:
        object:
          type: string
          enum:
            - mcp_oauth_callback
        oauth_configured:
          type: boolean
          enum:
            - true
          description: >-
            Always true when the endpoint returns success; the flow only
            completes if the token exchange succeeded.
        tools_synced:
          type: boolean
          description: >-
            True if Datagrid automatically re-synced the MCP server's tool
            manifest after the OAuth exchange. False if the caller lacks
            organization-edit permissions or the sync itself failed.
        message:
          type: string
          description: >-
            Human-readable outcome. Optional product copy — branch on
            `oauth_configured` and `tools_synced` rather than matching this
            text.
    McpOAuthRequiresUserPrincipalError:
      type: object
      description: >-
        Returned when a service key is used to start or complete a per-user MCP
        OAuth flow. Per-user tokens are bound to a human user, so service keys
        (`dg_svc_`) are rejected.
      required:
        - error
        - message
        - retryable
        - status_code
      properties:
        status_code:
          type: integer
          description: The HTTP status code (403).
        statusCode:
          type: integer
          deprecated: true
          description: Deprecated. Use status_code instead.
        error:
          type: string
          enum:
            - mcp_oauth_requires_user_principal
          description: >-
            The error code identifying this as a service-key rejection on a
            per-user MCP OAuth endpoint.
        message:
          type: string
          description: A human-readable error message.
        mitigation:
          type: string
          description: Suggested action to resolve the error.
        retryable:
          type: boolean
          enum:
            - false
          description: Whether the request can be retried. Always false for this error.
        details:
          type: object
    RateLimitError:
      type: object
      description: >-
        Returned when the rate limit is exceeded. Rate limits are enforced per
        teamspace, endpoint path, and HTTP method over a 60-second sliding
        window. Each endpoint may have its own limit — check the
        X-RateLimit-Limit response header for the effective value.
      required:
        - error
        - message
        - retryable
        - status_code
      properties:
        status_code:
          type: integer
          description: The HTTP status code (429).
        statusCode:
          type: integer
          deprecated: true
          description: Deprecated. Use status_code instead.
        error:
          type: string
          enum:
            - rate_limit_exceeded
          description: The error code identifying this as a rate limit error.
        message:
          type: string
          description: A human-readable error message.
        mitigation:
          type: string
          description: Suggested action to resolve the error.
        retryable:
          type: boolean
          description: Whether the request can be retried after a delay.
        details:
          type: object
          properties:
            reason:
              type: string
              description: A detailed explanation of why the rate limit was exceeded.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

````