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

# Import from OpenAPI

> Parse an OpenAPI 3.x spec and import the selected operations as tools.

This endpoint accepts an OpenAPI 3.x JSON or YAML spec and runs a **two-phase import**: the first call returns a list of candidate tools (one per operation), the second call commits the selection.

<Note>
  Phase 1 (no `commit` flag) parses the spec and returns candidates with `temp_id`s — no tools are created. Phase 2 (`commit: true`) takes the same body plus `selected_temp_ids` and writes the chosen tools to the database. This mirrors the import wizard in the admin UI.
</Note>

<Note>
  Imported tools default to status `draft` so a careless import never silently exposes half-baked tools to MCP clients. Pass `imported_status: "active"` on the commit call when you've reviewed the candidates and want them live immediately.
</Note>

## Path Parameters

<ParamField path="server_id" type="string" required>
  The UUID of the server to import into (e.g. `836995ae-1cff-41ec-823e-a4f07ccca3a0`). Numeric IDs are also accepted for backwards compatibility.
</ParamField>

## Body Parameters

<ParamField body="source" type="string" default="text">
  Where the spec content comes from. One of: `text` (use `content`), `url` (use `url`).
</ParamField>

<ParamField body="content" type="string">
  The raw spec body (JSON or YAML). Required when `source` is `text`. Hard cap of 10 MB.
</ParamField>

<ParamField body="url" type="string">
  Public URL to fetch the spec from. Required when `source` is `url`. Followed up to 3 redirects, 10 s timeout, 10 MB cap.
</ParamField>

<ParamField body="commit" type="boolean" default="false">
  When `false` (default), parse the spec and return candidates without writing anything. When `true`, persist the candidates listed in `selected_temp_ids`.
</ParamField>

<ParamField body="selected_temp_ids" type="array">
  Array of `temp_id` strings (returned by the parse phase) identifying which candidates to create. Required when `commit` is `true`. Anything not in the list is silently ignored.
</ParamField>

<ParamField body="on_conflict" type="string" default="skip">
  How to handle slug collisions during commit. One of: `skip` (default — record goes into `skipped[]`), `duplicate` (let `ToolManager` auto-suffix the slug).
</ParamField>

<ParamField body="imported_status" type="string" default="draft">
  Status for newly created tools during commit. One of: `draft`, `active`. Defaults to `draft` for safety.
</ParamField>

<RequestExample>
  ```bash cURL — Phase 1 (parse) theme={null}
  curl --request POST \
       --url https://yoursite.com/wp-json/getmcp/v1/servers/836995ae-1cff-41ec-823e-a4f07ccca3a0/tools/import-openapi \
       --header 'Authorization: Bearer gmcp_your_api_key' \
       --header 'content-type: application/json' \
       --data '{
         "source": "url",
         "url": "https://petstore3.swagger.io/api/v3/openapi.json"
       }'
  ```

  ```bash cURL — Phase 2 (commit) theme={null}
  curl --request POST \
       --url https://yoursite.com/wp-json/getmcp/v1/servers/836995ae-1cff-41ec-823e-a4f07ccca3a0/tools/import-openapi \
       --header 'Authorization: Bearer gmcp_your_api_key' \
       --header 'content-type: application/json' \
       --data '{
         "source": "url",
         "url": "https://petstore3.swagger.io/api/v3/openapi.json",
         "commit": true,
         "selected_temp_ids": ["op_0", "op_3", "op_7"],
         "on_conflict": "skip",
         "imported_status": "draft"
       }'
  ```

  ```python Python theme={null}
  import requests

  base = "https://yoursite.com/wp-json/getmcp/v1/servers/836995ae-1cff-41ec-823e-a4f07ccca3a0/tools/import-openapi"
  headers = {
      "Authorization": "Bearer gmcp_your_api_key",
      "Content-Type": "application/json",
  }

  # Phase 1 — parse and inspect candidates.
  parse = requests.post(base, headers=headers, json={
      "source": "url",
      "url": "https://petstore3.swagger.io/api/v3/openapi.json",
  }).json()
  print(parse["candidates"])

  # Phase 2 — commit a subset.
  commit = requests.post(base, headers=headers, json={
      "source": "url",
      "url": "https://petstore3.swagger.io/api/v3/openapi.json",
      "commit": True,
      "selected_temp_ids": [c["temp_id"] for c in parse["candidates"][:3]],
      "imported_status": "draft",
  }).json()
  print(commit)
  ```

  ```javascript JavaScript theme={null}
  const url = "https://yoursite.com/wp-json/getmcp/v1/servers/836995ae-1cff-41ec-823e-a4f07ccca3a0/tools/import-openapi";
  const headers = {
    "Authorization": "Bearer gmcp_your_api_key",
    "Content-Type": "application/json",
  };

  const parse = await (await fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify({
      source: "text",
      content: "openapi: 3.0.0\ninfo:\n  title: Demo\n...",
    }),
  })).json();

  const commit = await (await fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify({
      source: "text",
      content: parse._raw_spec,
      commit: true,
      selected_temp_ids: parse.candidates.map(c => c.temp_id),
      imported_status: "active",
    }),
  })).json();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK — Phase 1 (parse) theme={null}
  {
    "candidates": [
      {
        "temp_id": "op_0",
        "name": "List Pets",
        "slug": "list_pets",
        "description": "Returns all pets from the system that the user has access to.",
        "endpoint_url": "https://petstore3.swagger.io/api/v3/pet/findByStatus",
        "http_method": "GET",
        "input_schema": {
          "type": "object",
          "properties": {
            "status": { "type": "string", "enum": ["available", "pending", "sold"] }
          },
          "required": ["status"]
        },
        "headers": null,
        "tags": ["pet"]
      }
    ],
    "info": {
      "title": "Swagger Petstore",
      "version": "1.0.11"
    }
  }
  ```

  ```json 200 OK — Phase 2 (commit) theme={null}
  {
    "created": [
      { "tool_id": 42, "uuid": "5376af81-6bb8-4b01-800c-508d7672e394", "name": "List Pets", "slug": "list_pets" }
    ],
    "skipped": [
      { "temp_id": "op_3", "name": "Get Pet By ID", "reason": "slug_exists" }
    ],
    "failed": []
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "code": "invalid_spec",
    "message": "Empty content.",
    "data": { "status": 400 }
  }
  ```

  ```json 400 Bad Request — version mismatch theme={null}
  {
    "code": "unsupported_version",
    "message": "unsupported_version: spec is Swagger 2.0 — use the import-swagger endpoint.",
    "data": { "status": 400 }
  }
  ```

  ```json 403 Forbidden — tier limit theme={null}
  {
    "code": "tier_limit_import_method",
    "message": "Importing tools from OPENAPI is not available on your FREE plan.",
    "data": {
      "status": 403,
      "tier": "free",
      "upgrade_url": "https://getmcp.com/pricing"
    }
  }
  ```
</ResponseExample>

## Status Codes

| Code  | Meaning                                                     |
| ----- | ----------------------------------------------------------- |
| `200` | Spec parsed (phase 1) or commit completed (phase 2).        |
| `400` | Bad spec, empty content, wrong version, or unfetchable URL. |
| `402` | 14-day trial expired and no active license.                 |
| `403` | Current license tier does not allow OpenAPI import.         |
| `404` | Server not found.                                           |
