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

# Stream a Chat Completion (SSE)

> For clients that don't speak MCP JSON-RPC. Appends one user message to the `(workspace x x-session-id)` conversation, runs the agent loop, and streams the response as a `text/event-stream`. Reuse the same `x-session-id` across calls to continue the same conversation — the server persists message history per session.

**Stateless workspaces:** if the workspace has `statelessMode: true`, nothing is persisted and the `x-session-id` header is ignored. Instead, supply prior turns yourself via the request body's `history` array (up to 200 turns; the current message stays in `message`). Sending `history` to a non-stateless workspace returns 400. `statelessMode` is a workspace setting and cannot be overridden per request.

**SSE event types:** `message_delta` (incremental assistant text), `tool_call_start`, `tool_call_result`, `tool_calls_complete`, `usage` (token counts), `done` (stream end), and `error`.



## OpenAPI

````yaml POST /mcp/{workspaceId}/chat
openapi: 3.0.0
info:
  title: RouteMCP API
  description: >-
    Unified API for integrations. Connect to multiple providers through a single
    API.
  version: '1.0'
  contact: {}
servers:
  - url: https://api.routemcp.io/api/v1
    description: Production
security:
  - bearerAuth: []
tags: []
paths:
  /mcp/{workspaceId}/chat:
    post:
      tags:
        - HTTP Streaming Chat
      summary: Stream a chat completion (Server-Sent Events)
      description: >-
        For clients that don't speak MCP JSON-RPC. Appends one user message to
        the `(workspace x x-session-id)` conversation, runs the agent loop, and
        streams the response as a `text/event-stream`. Reuse the same
        `x-session-id` across calls to continue the same conversation — the
        server persists message history per session.


        **Stateless workspaces:** if the workspace has `statelessMode: true`,
        nothing is persisted and the `x-session-id` header is ignored. Instead,
        supply prior turns yourself via the request body's `history` array (up
        to 200 turns; the current message stays in `message`). Sending `history`
        to a non-stateless workspace returns 400. `statelessMode` is a workspace
        setting and cannot be overridden per request.


        **SSE event types:** `message_delta` (incremental assistant text),
        `tool_call_start`, `tool_call_result`, `tool_calls_complete`, `usage`
        (token counts), `done` (stream end), and `error`.
      operationId: McpChatController_sendMessage
      parameters:
        - name: workspaceId
          in: path
          required: true
          description: Workspace (MCP server) UUID to route the chat through.
          schema:
            type: string
            format: uuid
        - name: x-session-id
          in: header
          required: true
          description: >-
            Conversation id — must be a valid UUID. The same value across
            requests resumes the same chat; a new value starts a fresh
            conversation.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendChatMessageDto'
            example:
              message: Hello
      responses:
        '200':
          description: >-
            Server-Sent Events stream of the agent loop's response. Parse
            `event:`/`data:` frames; the stream ends with a `done` event.
          content:
            text/event-stream:
              schema:
                type: string
                description: >-
                  An SSE stream. Each frame is `event: <type>\ndata:
                  <json>\n\n`.
              example: |+
                event: message_delta
                data: {"text":"Hi"}

                event: tool_call_start
                data: {"id":"call_1","name":"github_list_repos"}

                event: tool_call_result
                data: {"id":"call_1","result":{...}}

                event: tool_calls_complete
                data: {}

                event: message_delta
                data: {"text":" there!"}

                event: usage
                data: {"inputTokens":1234,"outputTokens":56}

                event: done
                data: {}

        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    example: false
                  statusCode:
                    type: integer
                    example: 400
                    default: 400
                  message:
                    type: string
                    example: x-session-id must be a valid UUID
                    default: Bad Request
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-02-06T12:00:00.000Z'
                  path:
                    type: string
                    example: /api/v1/example
                required:
                  - success
                  - statusCode
                  - message
                  - timestamp
                  - path
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    example: false
                  statusCode:
                    type: integer
                    example: 401
                    default: 401
                  message:
                    type: string
                    example: Invalid or missing API key
                    default: Unauthorized
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-02-06T12:00:00.000Z'
                  path:
                    type: string
                    example: /api/v1/example
                required:
                  - success
                  - statusCode
                  - message
                  - timestamp
                  - path
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    example: false
                  statusCode:
                    type: integer
                    example: 404
                    default: 404
                  message:
                    type: string
                    example: mcp server <id> not found
                    default: Not Found
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-02-06T12:00:00.000Z'
                  path:
                    type: string
                    example: /api/v1/example
                required:
                  - success
                  - statusCode
                  - message
                  - timestamp
                  - path
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    example: false
                  statusCode:
                    type: integer
                    example: 429
                    default: 429
                  message:
                    type: string
                    example: Too Many Requests
                    default: Too Many Requests
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-02-06T12:00:00.000Z'
                  path:
                    type: string
                    example: /api/v1/example
                required:
                  - success
                  - statusCode
                  - message
                  - timestamp
                  - path
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    example: false
                  statusCode:
                    type: integer
                    example: 500
                    default: 500
                  message:
                    type: string
                    example: Internal server error.
                    default: Internal server error.
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-02-06T12:00:00.000Z'
                  path:
                    type: string
                    example: /api/v1/example
                required:
                  - success
                  - statusCode
                  - message
                  - timestamp
                  - path
      security:
        - bearerAuth: []
components:
  schemas:
    SendChatMessageDto:
      type: object
      properties:
        message:
          type: string
          minLength: 1
          maxLength: 50000
          description: >-
            The user message for this turn. This is the CURRENT message only —
            prior turns go in `history` (stateless workspaces) or are loaded
            from the persisted session (stateful workspaces).
          example: Hello
        context:
          type: string
          maxLength: 50000
          description: >-
            Optional free-text background about the end-user (e.g. an email
            signature, preferred tone, defaults). When non-empty it is injected
            into the agent so it can apply it when calling tools. On a stateful
            workspace it is stored encrypted and sticky for the end-user (keyed
            by the x-session-id header); on a stateless workspace it is injected
            for this request only and NEVER stored. Omit or send an empty string
            to keep any previously stored value; a new non-empty value
            overwrites it. Max 50000 characters.
        history:
          type: array
          maxItems: 200
          description: >-
            Caller-supplied PRIOR conversation turns, accepted ONLY when the
            workspace is in `statelessMode`. Sending `history` to a
            non-stateless workspace returns 400. Excludes the current message
            (which stays in `message`). Up to 200 items; each item's `message`
            is capped at ~50,000 characters.
          items:
            type: object
            properties:
              role:
                type: string
                enum:
                  - user
                  - assistant
                example: user
              message:
                type: string
                minLength: 1
                maxLength: 50000
                example: What repos do I have?
            required:
              - role
              - message
          example:
            - role: user
              message: What repos do I have?
            - role: assistant
              message: 'You have 3 repositories: api, web, and docs.'
      required:
        - message
  securitySchemes:
    bearerAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Enter your API key with the Bearer prefix — e.g. Bearer sk_live_xxx
        (production) or Bearer sk_test_xxx (sandbox)

````