openapi: 3.0.3
info:
  title: Trupocket API - Model Context Protocol (MCP)
  version: 1.0.0
  description: |
    Trupocket exposes a per-household **Model Context Protocol (MCP)** server so AI
    assistants (Claude, ChatGPT, Copilot, Gemini CLI, and any MCP-compatible client)
    can securely **read** a household's finances and answer questions like
    "where did my money go?", "am I on budget?", and "when will this loan be paid off?".

    The MCP endpoint speaks the MCP wire protocol (JSON-RPC over **Streamable HTTP**) —
    it is **not** a normal REST/JSON endpoint. Point an MCP client at the endpoint URL
    and authenticate with a Personal Access Token.

    ## Connecting
    - **Endpoint:** `POST/GET https://api.trupocket.app/v1/households/{householdID}/detailed-tracking/mcp`
    - **Auth:** send a Personal Access Token (created under Users › Access Tokens) as a
      bearer token: `Authorization: Bearer tp_...`. OAuth one-click connect for consumer
      apps is offered separately via the discovery documents below.
    - **Discovery:** unauthenticated clients receive a `401` with a `WWW-Authenticate`
      header pointing at the protected-resource metadata document.

    ## Plan requirements
    MCP access requires a **Premium**, **Developer**, or **Enterprise** plan. Free-plan
    households receive `402 plan-upgrade-required`. Reports that reach beyond a plan's data
    history window return a clear "upgrade for more history" message.

    ## Available read-only tools
    - **Accounts:** `list_accounts`, `get_account`, `get_net_worth`
    - **Transactions:** `list_transactions`, `get_transaction`
    - **Budgets:** `list_categories`
    - **Reference:** `list_payees`, `list_hashtags`, `list_scheduled_transactions`
    - **Reports:** `get_monthly_cashflow`, `get_budget_spending`, `get_spending`,
      `get_top_spending`, `get_forecast`, `get_monthly_footprint`,
      `get_loan_payment_history`, `get_loan_amortization`, `get_credit_card_amortization`
    - **Overview:** `get_financial_snapshot`

    All tools are read-only; no tool can create, modify, or delete data.

servers:
  - url: https://api.trupocket.app
    description: Production API

tags:
  - name: MCP
    description: Model Context Protocol server and discovery documents

paths:
  /.well-known/oauth-protected-resource:
    get:
      tags: [MCP]
      summary: OAuth Protected Resource Metadata (discovery)
      description: >
        Public discovery document (RFC 9728) that MCP clients fetch to learn how to
        authenticate with the MCP endpoint. Returned in the `WWW-Authenticate` challenge
        on a 401 from the MCP endpoint. No authentication required.
      operationId: getProtectedResourceMetadata
      security: []
      responses:
        "200":
          description: Protected resource metadata
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProtectedResourceMetadata"

  /v1/households/{householdID}/detailed-tracking/mcp:
    post:
      tags: [MCP]
      summary: MCP server (Streamable HTTP)
      description: >
        The household's MCP server. Speaks the MCP protocol (JSON-RPC over Streamable
        HTTP), so it should be used with an MCP client rather than called directly. POST
        carries JSON-RPC requests (e.g. `initialize`, `tools/list`, `tools/call`); GET
        opens the optional server-sent event stream. Authenticate with a Personal Access
        Token. Requires a Premium, Developer, or Enterprise plan.
      operationId: mcpStreamableHTTP
      parameters:
        - $ref: "components.yaml#/components/parameters/HouseholdID"
        - name: Accept
          in: header
          required: true
          schema:
            type: string
            example: application/json, text/event-stream
          description: Must include both application/json and text/event-stream.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: A JSON-RPC 2.0 request as defined by the MCP specification.
      responses:
        "200":
          description: MCP protocol response (JSON-RPC result or SSE stream).
          content:
            application/json:
              schema:
                type: object
                description: A JSON-RPC 2.0 response as defined by the MCP specification.
        "401":
          description: >
            Missing or invalid access token. The response includes a `WWW-Authenticate`
            header pointing at the protected-resource metadata document.
          headers:
            WWW-Authenticate:
              schema:
                type: string
                example: 'Bearer resource_metadata="https://api.trupocket.app/.well-known/oauth-protected-resource", scope="trupocket-api/read"'
              description: >
                Bearer challenge referencing the protected-resource metadata document and
                the required `trupocket-api/read` scope.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
        "402":
          description: The household's plan does not include MCP access. Upgrade required.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
              example:
                errorCode: plan-upgrade-required
                errorMessage: MCP access requires a Premium, Developer, or Enterprise plan. Please upgrade to use AI features.
                errorField: null
        "403":
          description: >
            The presented OAuth access token is missing the required `trupocket-api/read`
            scope. Personal Access Tokens are unscoped and are not subject to this check.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
              example:
                errorCode: insufficient_scope
                errorMessage: This access token is missing the required trupocket-api/read scope
        "404":
          description: The household does not exist or is not accessible to this user.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
        "501":
          description: MCP support is not currently enabled on the server.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
    get:
      tags: [MCP]
      summary: MCP server SSE stream (Streamable HTTP)
      description: >
        Opens the optional server-sent event stream for the MCP Streamable HTTP transport.
        Same authentication and plan requirements as the POST method.
      operationId: mcpStreamableHTTPStream
      parameters:
        - $ref: "components.yaml#/components/parameters/HouseholdID"
      responses:
        "200":
          description: Server-sent event stream of MCP messages.
        "401":
          description: Missing or invalid access token.
          headers:
            WWW-Authenticate:
              schema:
                type: string
                example: 'Bearer resource_metadata="https://api.trupocket.app/.well-known/oauth-protected-resource", scope="trupocket-api/read"'
              description: >
                Bearer challenge referencing the protected-resource metadata document and
                the required `trupocket-api/read` scope.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
        "402":
          description: The household's plan does not include MCP access. Upgrade required.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
        "403":
          description: >
            The presented OAuth access token is missing the required `trupocket-api/read`
            scope. Personal Access Tokens are unscoped and are not subject to this check.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
              example:
                errorCode: insufficient_scope
                errorMessage: This access token is missing the required trupocket-api/read scope
        "404":
          description: The household does not exist or is not accessible to this user.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"
        "501":
          description: MCP support is not currently enabled on the server.
          content:
            application/json:
              schema:
                $ref: "components.yaml#/components/schemas/Error"

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      $ref: "components.yaml#/components/securitySchemes/BearerAuth"
  schemas:
    ProtectedResourceMetadata:
      type: object
      description: OAuth 2.0 Protected Resource Metadata (RFC 9728).
      properties:
        resource:
          type: string
          example: https://api.trupocket.app
        authorization_servers:
          type: array
          items:
            type: string
          example: ["https://api.trupocket.app"]
        scopes_supported:
          type: array
          items:
            type: string
          example: ["openid", "profile", "email", "trupocket-api/read", "trupocket-api/write"]
        bearer_methods_supported:
          type: array
          items:
            type: string
          example: ["header"]
        resource_documentation:
          type: string
          example: https://api.trupocket.app/docs
