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

# Register an agent or an MCP server (atomic prove-then-persist)

> Fires a live round-trip and persists the target ONLY if the probe succeeds; a failed probe persists nothing and returns a categorized error (unreachable / auth_failed / parse_error / no_reply / not_an_endpoint). Pass 'config' for an agent: static auth (none/bearer/api_key/basic) or oauth_client_credentials, over http or websocket. Pass 'mcp' for an MCP server: none/bearer/api_key, over streamable HTTP or SSE; its probe connects, signs in and lists what the server offers. The response never echoes the config, credential, or reply. The returned model_id is the handle for POST /api/v1/run. List first via GET /api/v1/model — creates are not deduplicated.



## OpenAPI

````yaml /openapi.json post /api/v1/model
openapi: 3.1.0
info:
  title: Enoki External API
  description: >-
    Programmatic API for CI/CD integration. Authenticate with `Authorization:
    Bearer egk_...`.
  version: 0.1.0
servers:
  - url: https://api.enokilabs.ai
    description: Enoki API
security: []
paths:
  /api/v1/model:
    post:
      tags:
        - integration
      summary: Register an agent or an MCP server (atomic prove-then-persist)
      description: >-
        Fires a live round-trip and persists the target ONLY if the probe
        succeeds; a failed probe persists nothing and returns a categorized
        error (unreachable / auth_failed / parse_error / no_reply /
        not_an_endpoint). Pass 'config' for an agent: static auth
        (none/bearer/api_key/basic) or oauth_client_credentials, over http or
        websocket. Pass 'mcp' for an MCP server: none/bearer/api_key, over
        streamable HTTP or SSE; its probe connects, signs in and lists what the
        server offers. The response never echoes the config, credential, or
        reply. The returned model_id is the handle for POST /api/v1/run. List
        first via GET /api/v1/model — creates are not deduplicated.
      operationId: api_create_target_api_v1_model_post
      parameters:
        - name: Authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Bearer token with API key
            title: Authorization
          description: Bearer token with API key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApiCreateTargetRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiCreateTargetResponse'
        '400':
          description: Endpoint URL rejected (scheme or private/internal address)
        '422':
          description: >-
            Two distinct shapes share this status. A **probe failure** returns
            `detail` as an **object** (`error_category` + a redacted message,
            shown below). A **request-validation** error returns the standard
            FastAPI `detail` as a **list** of per-field errors. Clients must
            branch on the type of `detail` (object vs list) rather than assume
            the validation shape.
          content:
            application/json:
              example:
                detail:
                  error: probe_failed
                  error_category: unreachable
                  message: Could not reach the target endpoint.
components:
  schemas:
    ApiCreateTargetRequest:
      properties:
        name:
          type: string
          maxLength: 200
          minLength: 1
          title: Name
          description: Display name for the target.
        environment:
          type: string
          enum:
            - prod
            - staging
            - dev
          title: Environment
          default: staging
        auth_type:
          type: string
          enum:
            - none
            - bearer
            - api_key
            - basic
            - oauth_client_credentials
          title: Auth Type
          description: >-
            bearer='Authorization: Bearer <cred>', api_key='x-api-key: <cred>',
            basic=HTTP Basic with the credential as 'user:password',
            oauth_client_credentials=an access token minted from the 'oauth'
            config below and re-minted before it expires. No enterprise auth. An
            MCP server takes none, bearer or api_key, which sends the credential
            in mcp.api_key_header.
          default: none
        credential:
          anyOf:
            - type: string
              minLength: 5
            - type: 'null'
          title: Credential
          description: >-
            Required for bearer/api_key/basic, and the OAuth client secret for
            oauth_client_credentials; omit for none. Stored encrypted, never
            returned.
        config:
          anyOf:
            - $ref: '#/components/schemas/ApiAgentConfig'
            - type: 'null'
          description: >-
            An agent's connection. Endpoint transport/parsing config
            (endpoint_url, response_field dot-path, transport, ...). Use
            request_timeout (<=180); ws_timeout is ignored here. Exactly one of
            'config' and 'mcp'.
        mcp:
          anyOf:
            - $ref: '#/components/schemas/ApiMcpServerConfig'
            - type: 'null'
          description: >-
            An MCP server instead of an agent: its endpoint and transport.
            Exactly one of 'config' and 'mcp'.
        oauth:
          anyOf:
            - $ref: '#/components/schemas/ApiOAuthClientCredentialsConfig'
            - type: 'null'
          description: >-
            Required for auth_type='oauth_client_credentials', rejected
            otherwise. The token request that mints the bearer (token_url,
            client_id, and optionally scope/audience). Carries no secret — the
            client secret is 'credential'.
      type: object
      required:
        - name
      title: ApiCreateTargetRequest
      description: >-
        Request body for `POST /api/v1/model` (register an agent or an MCP
        server).
    ApiCreateTargetResponse:
      properties:
        model_id:
          type: string
          title: Model Id
          description: Inventory model id — use directly as model_id in POST /api/v1/run.
        connected:
          type: boolean
          const: true
          title: Connected
          description: 'Always true: the target is persisted only after a successful probe.'
      type: object
      required:
        - model_id
        - connected
      title: ApiCreateTargetResponse
      description: >-
        Response for `POST /api/v1/model` (201).


        The inventory id and the connection verdict only. It never echoes the
        config

        (it may hold a header secret), the credential, or any part of the
        target's

        reply.
    ApiAgentConfig:
      properties:
        endpoint_url:
          type: string
          title: Endpoint Url
        request_field:
          type: string
          title: Request Field
          default: message
        response_field:
          type: string
          title: Response Field
          default: response
        session_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Field
          default: session_id
        session_response_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Response Field
        session_response_header_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Session Response Header Field
        session_id_numeric:
          type: boolean
          title: Session Id Numeric
          default: false
        transport:
          type: string
          enum:
            - http
            - websocket
          title: Transport
          default: http
        http_stream_format:
          type: string
          enum:
            - sync
            - jsonl
            - sse
          title: Http Stream Format
          default: sync
        chunk_combination:
          type: string
          enum:
            - concatenate
            - replace
          title: Chunk Combination
          default: concatenate
        chunk_skip_roles:
          items:
            type: string
          type: array
          title: Chunk Skip Roles
        extra_http_headers:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
          title: Extra Http Headers
        request_body_template:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Request Body Template
        ws_auth_method:
          anyOf:
            - type: string
              enum:
                - query_param
                - header
                - post_connect
            - type: 'null'
          title: Ws Auth Method
        ws_auth_endpoint:
          type: 'null'
          title: Ws Auth Endpoint
        ws_url_endpoint:
          type: 'null'
          title: Ws Url Endpoint
        ws_request_extra_fields:
          anyOf:
            - additionalProperties:
                anyOf:
                  - type: string
                  - type: integer
                  - type: number
                  - type: boolean
              type: object
            - type: 'null'
          title: Ws Request Extra Fields
        ws_event_type_field:
          type: string
          title: Ws Event Type Field
          default: type
        ws_done_event_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Done Event Type
        ws_result_extract_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Result Extract Field
        ws_stream_extract_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Ws Stream Extract Field
        request_timeout:
          type: number
          maximum: 180
          exclusiveMinimum: 0
          title: Request Timeout
          default: 180
        reply_fetch:
          anyOf:
            - $ref: '#/components/schemas/ReplyFetchConfig'
            - type: 'null'
      type: object
      required:
        - endpoint_url
      title: ApiAgentConfig
      description: 'How to reach the agent: its endpoint, transport and where its reply is.'
    ApiMcpServerConfig:
      properties:
        endpoint_url:
          type: string
          maxLength: 2048
          minLength: 1
          title: Endpoint Url
          description: The server's MCP endpoint, e.g. https://mcp.example.com/mcp.
        transport:
          type: string
          enum:
            - http
            - sse
          title: Transport
          description: >-
            'http' for streamable HTTP, the default, or 'sse' for the older SSE
            transport.
          default: http
        api_key_header:
          anyOf:
            - type: string
              maxLength: 128
              minLength: 1
              pattern: ^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
            - type: 'null'
          title: Api Key Header
          description: >-
            The header an API key is sent in, for auth_type 'api_key'. Defaults
            to X-API-Key.
      additionalProperties: false
      type: object
      required:
        - endpoint_url
      title: ApiMcpServerConfig
      description: Where an MCP server is reached.
    ApiOAuthClientCredentialsConfig:
      properties:
        token_url:
          type: string
          title: Token Url
          description: >-
            The OAuth 2.0 token endpoint. Absolute URL; https is required unless
            the platform allows private targets.
        client_id:
          type: string
          title: Client Id
          description: OAuth client identifier.
        scope:
          anyOf:
            - type: string
            - type: 'null'
          title: Scope
          description: >-
            Space-delimited scopes, when the provider expects them (Okta, Azure,
            ...).
        audience:
          anyOf:
            - type: string
            - type: 'null'
          title: Audience
          description: >-
            Audience parameter, for providers that require it instead of scope
            (Auth0).
        extra_params:
          additionalProperties:
            type: string
          type: object
          title: Extra Params
          description: >-
            Additional form fields for the token request, for providers wanting
            something neither scope nor audience covers. Carries no secret.
        client_auth_method:
          type: string
          enum:
            - post
            - basic
          title: Client Auth Method
          description: >-
            How the client credentials are presented: 'post' sends client_id +
            client_secret in the form body; 'basic' sends them as HTTP Basic.
          default: post
      type: object
      required:
        - token_url
        - client_id
      title: ApiOAuthClientCredentialsConfig
      description: How to mint an access token for the agent with OAuth client credentials.
    ReplyFetchConfig:
      properties:
        url:
          type: string
          title: Url
          description: >-
            GET URL of the message list, on the endpoint's host. May contain
            __SESSION_ID__.
        messages_field:
          type: string
          title: Messages Field
          description: Dot-path to the list of messages.
        role_field:
          type: string
          title: Role Field
          description: Dot-path, within a message, to its author role.
        reply_roles:
          items:
            type: string
          type: array
          minItems: 1
          title: Reply Roles
          description: Role values that mark the bot's messages.
        text_field:
          type: string
          title: Text Field
          description: Dot-path, within a message, to its text.
        anchor_id_field:
          anyOf:
            - type: string
            - type: 'null'
          title: Anchor Id Field
          description: >-
            Dot-path, in the POST response, to our message's id; messages after
            it are candidate replies. Unset: the anchor is the last message
            whose text is ours.
        item_id_field:
          type: string
          title: Item Id Field
          description: Dot-path, within a message, to its id, matched to the anchor.
          default: id
        poll_interval_seconds:
          type: number
          maximum: 10
          exclusiveMinimum: 0
          title: Poll Interval Seconds
          default: 1.5
        deadline_seconds:
          type: number
          maximum: 60
          exclusiveMinimum: 0
          title: Deadline Seconds
          default: 25
        settle_seconds:
          type: number
          maximum: 20
          minimum: 0
          title: Settle Seconds
          description: >-
            After the first reply, keep polling this long for more, then
            concatenate.
          default: 2
      type: object
      required:
        - url
        - messages_field
        - role_field
        - reply_roles
        - text_field
      title: ReplyFetchConfig
      description: |-
        How to read the reply of a target that answers after the POST.

        The POST returns only our message; the reply appears later in a message
        list served by a GET. List items are assumed oldest first.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.