# Execute API create operation (`execute_create`)

Runs one creating Sign Customiser API operation, named by the stable operation id search_operations returns, with typed path and body arguments. It reaches every create operation and nothing else: an update, a delete or a read is refused with the tool that does run it. Every call needs confirm: true, and an idempotency_key where the operation requires one. Setting dry_run: true checks the arguments through the operation validate twin and writes nothing. It requires the mcp:advanced scope plus the write scope the operation itself declares.

- Source URL: https://www.signcustomiser.com/help/mcp/tools/execute_create/
- Markdown URL: https://www.signcustomiser.com/help/mcp/tools/execute_create.md
- MCP endpoint: https://web.signcustomiser.com/mcp
- Required scope: none beyond a connected store
- Only visible to a connection granted `mcp:advanced`. Naming it without that scope answers `insufficient_scope`.
- Behaviour: write

## Purpose

Create anything the partner API can create, including the resources no curated tool covers, one operation per call.

## Annotations

| Hint | Value |
| --- | --- |
| readOnlyHint | false |
| destructiveHint | false |
| idempotentHint | true |
| openWorldHint | false |

## Prerequisites

- An operation id from search_operations, and its request_schema.
- A merchant has connected this store and approved mcp:advanced plus the write scope that operation requires.
- The merchant has agreed to the change: confirm: true is required on every call.

## Side effects

- Creates the record the operation creates, with whatever downstream effects that operation documents.
- Claims the idempotency_key for at least 24 hours where the operation requires one.

## Arguments

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `operation_id` | string | yes | The stable id of the operation to run, from search_operations. It is the only way to name an operation: this tool accepts no URL, no path and no HTTP method. |
| `path` | object | no | The operation path parameters, by name, exactly as search_operations lists them under parameters.path. An identifier the operation does not address is refused. |
| `query` | object | no | The query parameters, by name, as search_operations lists them under parameters.query. Only read operations take any; a nested object such as filter is sent as the API expects it. |
| `body` | object | no | The JSON request body, matching the operation request_schema from search_operations. It is passed to the API unchanged, so a member the operation does not accept comes back as unknown_field naming its pointer. A GET or a DELETE operation takes no body and refuses one. |
| `confirm` | boolean | no | Must be true to apply the change, because this tool can reach every create operation the API has and cannot judge the consequence of one on its own. Without it the call returns a confirmation_required error and changes nothing. A dry run does not need it. |
| `dry_run` | boolean | no | When true, the operation validate twin is checked and nothing is written: the result is the same verdict the apply would have reached, and a problem the apply would have raised comes back as the same tool error. Defaults to false. |
| `idempotency_key` | string | no | An optional client-generated key unique to this logical write, such as a UUID. Repeating the call with the same key and the same arguments replays the original result; the route does not require one. |

## Result

The operation own response data, unchanged, plus whether the call replayed a previous result rather than creating a second record.

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `request_id` | string | yes | The API request id, for support. |
| `store` | object | yes | The Store this connection resolved to. |
| `store.id` | integer | no |  |
| `store.name` | string | no |  |
| `operation_id` | string | yes | The operation that ran. |
| `status` | integer | yes | The HTTP status the operation answered with. |
| `dry_run` | boolean | no | Present and true when nothing was written. |
| `valid` | boolean | no | Present and true on a passing dry run. A failing dry run is a tool error carrying the problem the apply would have raised, never a verdict saying false. |
| `verdict` | object | no | What the validate twin reported about the operation. |
| `data` | object | no | The operation own response data, unchanged. |
| `idempotent_replay` | boolean | no | True when this call replayed a previously recorded response instead of creating a second record. |

## Error cases

| Code | Recovery |
| --- | --- |
| `confirmation_required` | Send confirm: true, or dry_run: true to check the arguments first. |
| `idempotency_key_conflict` | That key was used with different arguments. Re-send the original arguments, or issue a new key. |
| `insufficient_scope` | The connection holds mcp:advanced but not the write scope this operation needs. |
| `missing_idempotency_key` | The operation requires idempotency_key. search_operations reports which do, under idempotency. |
| `unsupported_value` | The id names an operation of another class, or has no validate twin for the dry run that was asked for. |
| `validation_failed` | The body does not satisfy the operation request_schema; the errors carry the pointer and allowed_values. |

## Example: Create a font tier no curated tool covers

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_create",
    "arguments": {
      "operation_id": "createFontTier",
      "path": {
        "customiser_id": 42
      },
      "body": {
        "name": "Premium",
        "price_multiplier": 1.25
      },
      "confirm": true,
      "idempotency_key": "9f8e7d6c-5b4a-4321-9876-543210fedcba"
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "operation_id": "createFontTier",
      "status": 201,
      "data": {
        "object": "font_tier",
        "id": 3,
        "name": "Premium",
        "price_multiplier": 1.25
      },
      "idempotent_replay": false
    }
  }
}
```

## Example: Without confirmation nothing is created (error)

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_create",
    "arguments": {
      "operation_id": "createFontTier",
      "path": {
        "customiser_id": 42
      },
      "body": {
        "name": "Premium"
      }
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "confirmation_required",
        "title": "Confirmation required",
        "detail": "Running createFontTier changes store data. It is one of 309 operations this tool can reach, so the confirmation is asked for every one of them.",
        "recovery": "This operation changes something consequential. Send confirm: true once the merchant has agreed to it.",
        "parameter": "confirm",
        "allowed_values": [
          "true"
        ]
      }
    }
  }
}
```
