{
  "openapi": "3.1.0",
  "info": {
    "title": "FluentEDI",
    "version": "1.0.0",
    "summary": "Deterministic tools for AI agents. No key, no signup, no SDK.",
    "description": "A public HTTP API of deterministic tools for the work a language model cannot do reliably by reasoning: knowing the current time in any timezone and whether an instant falls inside a window, exact arithmetic, hashing and signature verification, canonicalizing and content-addressing JSON, repairing malformed JSON and pinpointing where it broke, querying and diffing structured data, parsing CSV correctly, converting units and colours, testing regular expressions, resolving DNS, and checking whether a URL is still live. Every tool is one stateless GET or POST returning JSON, and the same tools are exposed over the Model Context Protocol at /mcp. Coverage runs deepest in retail EDI — X12 850, 856, 810, 855 and 997 parsing and validation, and GS1 check digits — which no other free, unauthenticated service offers agents.",
    "license": {
      "name": "Free to use",
      "identifier": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://fluentedi.com"
    }
  ],
  "tags": [
    {
      "name": "time",
      "description": "Time, dates and windows"
    },
    {
      "name": "schedule",
      "description": "Scheduling"
    },
    {
      "name": "data",
      "description": "JSON and tabular data"
    },
    {
      "name": "text",
      "description": "Text"
    },
    {
      "name": "crypto",
      "description": "Hashing, signatures, encoding and identifiers"
    },
    {
      "name": "compute",
      "description": "Calculation and conversion"
    },
    {
      "name": "web",
      "description": "Web and network"
    },
    {
      "name": "edi",
      "description": "EDI and retail supply chain (X12)"
    },
    {
      "name": "meta",
      "description": "Finding your way around"
    }
  ],
  "paths": {
    "/v1/time/now": {
      "get": {
        "operationId": "time_now_get",
        "summary": "Current date and time in any IANA timezone.",
        "description": "Returns the authoritative current time in one or more timezones, with UTC offset, ISO week number, day of year, weekend flag, and daylight-saving state. Use this instead of guessing the date: a language model has no clock, and its training cutoff is not today.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
            "schema": {
              "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          },
          {
            "name": "also",
            "in": "query",
            "required": false,
            "description": "Additional timezones to report alongside the primary one.",
            "schema": {
              "description": "Additional timezones to report alongside the primary one.",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              },
              "examples": [
                [
                  "Asia/Tokyo",
                  "Europe/Berlin"
                ]
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_now_post",
        "summary": "Current date and time in any IANA timezone.",
        "description": "Returns the authoritative current time in one or more timezones, with UTC offset, ISO week number, day of year, weekend flag, and daylight-saving state. Use this instead of guessing the date: a language model has no clock, and its training cutoff is not today.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "timezone": {
                    "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  },
                  "also": {
                    "description": "Additional timezones to report alongside the primary one.",
                    "type": "array",
                    "default": [],
                    "items": {
                      "type": "string"
                    },
                    "examples": [
                      [
                        "Asia/Tokyo",
                        "Europe/Berlin"
                      ]
                    ]
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/time/convert": {
      "get": {
        "operationId": "time_convert_get",
        "summary": "Convert a timestamp between timezones.",
        "description": "Converts one instant into any number of timezones, handling daylight saving transitions correctly. Naive inputs (no Z or offset) are read as wall-clock time in `from`; inputs carrying an offset are absolute.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "The instant to convert: ISO 8601, a naive wall-clock time, a unix timestamp, or \"now\".",
            "schema": {
              "description": "The instant to convert: ISO 8601, a naive wall-clock time, a unix timestamp, or \"now\".",
              "type": "string",
              "default": "now",
              "examples": [
                "2026-08-22T14:30:00"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Timezone the input is expressed in (used only when it carries no offset).",
            "schema": {
              "description": "Timezone the input is expressed in (used only when it carries no offset).",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Target timezones.",
            "schema": {
              "description": "Target timezones.",
              "type": "array",
              "default": [
                "UTC"
              ],
              "items": {
                "type": "string"
              },
              "examples": [
                [
                  "Asia/Tokyo",
                  "America/New_York"
                ]
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_convert_post",
        "summary": "Convert a timestamp between timezones.",
        "description": "Converts one instant into any number of timezones, handling daylight saving transitions correctly. Naive inputs (no Z or offset) are read as wall-clock time in `from`; inputs carrying an offset are absolute.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "time": {
                    "description": "The instant to convert: ISO 8601, a naive wall-clock time, a unix timestamp, or \"now\".",
                    "type": "string",
                    "default": "now",
                    "examples": [
                      "2026-08-22T14:30:00"
                    ]
                  },
                  "from": {
                    "description": "Timezone the input is expressed in (used only when it carries no offset).",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  },
                  "to": {
                    "description": "Target timezones.",
                    "type": "array",
                    "default": [
                      "UTC"
                    ],
                    "items": {
                      "type": "string"
                    },
                    "examples": [
                      [
                        "Asia/Tokyo",
                        "America/New_York"
                      ]
                    ]
                  }
                },
                "required": [
                  "to"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/time/add": {
      "get": {
        "operationId": "time_add_get",
        "summary": "Add or subtract a duration from a date, calendar-aware.",
        "description": "Adds years, months, weeks, days, hours, minutes and seconds to an instant. Calendar units (years, months, weeks, days) move wall-clock time and clamp overflow — Jan 31 plus one month is Feb 28 or 29, never Mar 3. Clock units (hours, minutes, seconds) add exact elapsed time and therefore cross DST boundaries.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "Starting instant: ISO 8601, unix timestamp, or \"now\".",
            "schema": {
              "description": "Starting instant: ISO 8601, unix timestamp, or \"now\".",
              "type": "string",
              "default": "now"
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
            "schema": {
              "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Years to add (negative subtracts).",
            "schema": {
              "description": "Years to add (negative subtracts).",
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "months",
            "in": "query",
            "required": false,
            "description": "Months to add (negative subtracts). Day-of-month is clamped.",
            "schema": {
              "description": "Months to add (negative subtracts). Day-of-month is clamped.",
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "weeks",
            "in": "query",
            "required": false,
            "description": "Weeks to add (negative subtracts).",
            "schema": {
              "description": "Weeks to add (negative subtracts).",
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Calendar days to add (negative subtracts).",
            "schema": {
              "description": "Calendar days to add (negative subtracts).",
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Exact hours to add (negative subtracts).",
            "schema": {
              "description": "Exact hours to add (negative subtracts).",
              "type": "number",
              "default": 0
            }
          },
          {
            "name": "minutes",
            "in": "query",
            "required": false,
            "description": "Exact minutes to add (negative subtracts).",
            "schema": {
              "description": "Exact minutes to add (negative subtracts).",
              "type": "number",
              "default": 0
            }
          },
          {
            "name": "seconds",
            "in": "query",
            "required": false,
            "description": "Exact seconds to add (negative subtracts).",
            "schema": {
              "description": "Exact seconds to add (negative subtracts).",
              "type": "number",
              "default": 0
            }
          },
          {
            "name": "business_days",
            "in": "query",
            "required": false,
            "description": "Weekdays to add, skipping Saturday and Sunday.",
            "schema": {
              "description": "Weekdays to add, skipping Saturday and Sunday.",
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_add_post",
        "summary": "Add or subtract a duration from a date, calendar-aware.",
        "description": "Adds years, months, weeks, days, hours, minutes and seconds to an instant. Calendar units (years, months, weeks, days) move wall-clock time and clamp overflow — Jan 31 plus one month is Feb 28 or 29, never Mar 3. Clock units (hours, minutes, seconds) add exact elapsed time and therefore cross DST boundaries.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "time": {
                    "description": "Starting instant: ISO 8601, unix timestamp, or \"now\".",
                    "type": "string",
                    "default": "now"
                  },
                  "timezone": {
                    "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  },
                  "years": {
                    "description": "Years to add (negative subtracts).",
                    "type": "integer",
                    "default": 0
                  },
                  "months": {
                    "description": "Months to add (negative subtracts). Day-of-month is clamped.",
                    "type": "integer",
                    "default": 0
                  },
                  "weeks": {
                    "description": "Weeks to add (negative subtracts).",
                    "type": "integer",
                    "default": 0
                  },
                  "days": {
                    "description": "Calendar days to add (negative subtracts).",
                    "type": "integer",
                    "default": 0
                  },
                  "hours": {
                    "description": "Exact hours to add (negative subtracts).",
                    "type": "number",
                    "default": 0
                  },
                  "minutes": {
                    "description": "Exact minutes to add (negative subtracts).",
                    "type": "number",
                    "default": 0
                  },
                  "seconds": {
                    "description": "Exact seconds to add (negative subtracts).",
                    "type": "number",
                    "default": 0
                  },
                  "business_days": {
                    "description": "Weekdays to add, skipping Saturday and Sunday.",
                    "type": "integer",
                    "default": 0
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/time/diff": {
      "get": {
        "operationId": "time_diff_get",
        "summary": "Duration between two dates, in every unit.",
        "description": "Computes the elapsed time between two instants: exact totals in each unit, a calendar breakdown (years/months/days rather than 'thirteen and a half months'), the count of weekdays in between, and a human phrase. Negative when `to` precedes `from`.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start instant: ISO 8601, unix timestamp, or \"now\".",
            "schema": {
              "description": "Start instant: ISO 8601, unix timestamp, or \"now\".",
              "type": "string",
              "default": "now",
              "examples": [
                "1990-05-14"
              ]
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "End instant: ISO 8601, unix timestamp, or \"now\".",
            "schema": {
              "description": "End instant: ISO 8601, unix timestamp, or \"now\".",
              "type": "string",
              "default": "now"
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
            "schema": {
              "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_diff_post",
        "summary": "Duration between two dates, in every unit.",
        "description": "Computes the elapsed time between two instants: exact totals in each unit, a calendar breakdown (years/months/days rather than 'thirteen and a half months'), the count of weekdays in between, and a human phrase. Negative when `to` precedes `from`.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from": {
                    "description": "Start instant: ISO 8601, unix timestamp, or \"now\".",
                    "type": "string",
                    "default": "now",
                    "examples": [
                      "1990-05-14"
                    ]
                  },
                  "to": {
                    "description": "End instant: ISO 8601, unix timestamp, or \"now\".",
                    "type": "string",
                    "default": "now"
                  },
                  "timezone": {
                    "description": "IANA timezone identifier, e.g. \"UTC\", \"America/New_York\", \"Asia/Kolkata\", \"Europe/London\".",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/time/window": {
      "get": {
        "operationId": "time_window_get",
        "summary": "Test whether an instant falls inside a time window, and by how much it misses.",
        "description": "Answers the questions a deadline actually poses: is this instant inside the window, how long until it opens or closes, and if it is outside, by how much. Optionally compares two windows for overlap. A window comparison that silently succeeds against the wrong bounds is a failure mode that does not raise an error anywhere — the ship window is missed, or the ASN is late, and the only symptom is a chargeback later. This computes the boundary instead of assuming it.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "start",
            "in": "query",
            "required": true,
            "description": "Window opens at this instant: ISO 8601, unix timestamp, or \"now\".",
            "schema": {
              "description": "Window opens at this instant: ISO 8601, unix timestamp, or \"now\".",
              "type": "string",
              "examples": [
                "2026-08-24T09:00:00Z"
              ]
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "Window closes at this instant. Omit if using `duration_hours`.",
            "schema": {
              "description": "Window closes at this instant. Omit if using `duration_hours`.",
              "type": "string",
              "default": ""
            }
          },
          {
            "name": "duration_hours",
            "in": "query",
            "required": false,
            "description": "Window length in hours, used when `end` is omitted.",
            "schema": {
              "description": "Window length in hours, used when `end` is omitted.",
              "type": "number",
              "default": 0
            }
          },
          {
            "name": "instant",
            "in": "query",
            "required": false,
            "description": "The instant to test against the window.",
            "schema": {
              "description": "The instant to test against the window.",
              "type": "string",
              "default": "now"
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone used to read naive inputs and render output.",
            "schema": {
              "description": "IANA timezone used to read naive inputs and render output.",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          },
          {
            "name": "compare_start",
            "in": "query",
            "required": false,
            "description": "Start of a second window, to test for overlap with the first.",
            "schema": {
              "description": "Start of a second window, to test for overlap with the first.",
              "type": "string",
              "default": ""
            }
          },
          {
            "name": "compare_end",
            "in": "query",
            "required": false,
            "description": "End of the second window.",
            "schema": {
              "description": "End of the second window.",
              "type": "string",
              "default": ""
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_window_post",
        "summary": "Test whether an instant falls inside a time window, and by how much it misses.",
        "description": "Answers the questions a deadline actually poses: is this instant inside the window, how long until it opens or closes, and if it is outside, by how much. Optionally compares two windows for overlap. A window comparison that silently succeeds against the wrong bounds is a failure mode that does not raise an error anywhere — the ship window is missed, or the ASN is late, and the only symptom is a chargeback later. This computes the boundary instead of assuming it.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "start": {
                    "description": "Window opens at this instant: ISO 8601, unix timestamp, or \"now\".",
                    "type": "string",
                    "examples": [
                      "2026-08-24T09:00:00Z"
                    ]
                  },
                  "end": {
                    "description": "Window closes at this instant. Omit if using `duration_hours`.",
                    "type": "string",
                    "default": ""
                  },
                  "duration_hours": {
                    "description": "Window length in hours, used when `end` is omitted.",
                    "type": "number",
                    "default": 0
                  },
                  "instant": {
                    "description": "The instant to test against the window.",
                    "type": "string",
                    "default": "now"
                  },
                  "timezone": {
                    "description": "IANA timezone used to read naive inputs and render output.",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  },
                  "compare_start": {
                    "description": "Start of a second window, to test for overlap with the first.",
                    "type": "string",
                    "default": ""
                  },
                  "compare_end": {
                    "description": "End of the second window.",
                    "type": "string",
                    "default": ""
                  }
                },
                "required": [
                  "start"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/time/zones": {
      "get": {
        "operationId": "time_zones_get",
        "summary": "List or search IANA timezone identifiers with current offsets.",
        "description": "Every IANA timezone the runtime supports, with its current UTC offset and local time. Search by city, region or offset to resolve a vague location like \"Bangalore\" to a valid identifier before calling other time tools.",
        "tags": [
          "time"
        ],
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Case-insensitive substring filter, e.g. \"kolkata\", \"america/\", \"+05:30\".",
            "schema": {
              "description": "Case-insensitive substring filter, e.g. \"kolkata\", \"america/\", \"+05:30\".",
              "type": "string",
              "default": ""
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results to return.",
            "schema": {
              "description": "Maximum results to return.",
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 700
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "time_zones_post",
        "summary": "List or search IANA timezone identifiers with current offsets.",
        "description": "Every IANA timezone the runtime supports, with its current UTC offset and local time. Search by city, region or offset to resolve a vague location like \"Bangalore\" to a valid identifier before calling other time tools.",
        "tags": [
          "time"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "search": {
                    "description": "Case-insensitive substring filter, e.g. \"kolkata\", \"america/\", \"+05:30\".",
                    "type": "string",
                    "default": ""
                  },
                  "limit": {
                    "description": "Maximum results to return.",
                    "type": "integer",
                    "default": 50,
                    "minimum": 1,
                    "maximum": 700
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/cron/next": {
      "get": {
        "operationId": "cron_next_get",
        "summary": "Validate a cron expression, explain it in English, and list its next run times.",
        "description": "Parses a standard 5-field cron expression (or 6-field with leading seconds, or a macro like @daily), validates it, describes it in plain English, and computes the next run times in a given timezone with daylight-saving handled. Use it before writing a schedule to config — cron's day-of-month/day-of-week OR-semantics and step syntax are a common source of silently wrong schedules.",
        "tags": [
          "schedule"
        ],
        "parameters": [
          {
            "name": "expression",
            "in": "query",
            "required": true,
            "description": "Cron expression, e.g. \"*/15 * * * *\", \"0 9 * * 1-5\", \"@daily\".",
            "schema": {
              "description": "Cron expression, e.g. \"*/15 * * * *\", \"0 9 * * 1-5\", \"@daily\".",
              "type": "string",
              "maxLength": 200,
              "examples": [
                "0 9 * * 1-5"
              ]
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "description": "IANA timezone the schedule runs in.",
            "schema": {
              "description": "IANA timezone the schedule runs in.",
              "type": "string",
              "default": "UTC",
              "examples": [
                "America/New_York"
              ]
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "How many upcoming run times to return.",
            "schema": {
              "description": "How many upcoming run times to return.",
              "type": "integer",
              "default": 5,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Compute run times after this instant instead of now.",
            "schema": {
              "description": "Compute run times after this instant instead of now.",
              "type": "string",
              "default": "now"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "cron_next_post",
        "summary": "Validate a cron expression, explain it in English, and list its next run times.",
        "description": "Parses a standard 5-field cron expression (or 6-field with leading seconds, or a macro like @daily), validates it, describes it in plain English, and computes the next run times in a given timezone with daylight-saving handled. Use it before writing a schedule to config — cron's day-of-month/day-of-week OR-semantics and step syntax are a common source of silently wrong schedules.",
        "tags": [
          "schedule"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expression": {
                    "description": "Cron expression, e.g. \"*/15 * * * *\", \"0 9 * * 1-5\", \"@daily\".",
                    "type": "string",
                    "maxLength": 200,
                    "examples": [
                      "0 9 * * 1-5"
                    ]
                  },
                  "timezone": {
                    "description": "IANA timezone the schedule runs in.",
                    "type": "string",
                    "default": "UTC",
                    "examples": [
                      "America/New_York"
                    ]
                  },
                  "count": {
                    "description": "How many upcoming run times to return.",
                    "type": "integer",
                    "default": 5,
                    "minimum": 1,
                    "maximum": 100
                  },
                  "from": {
                    "description": "Compute run times after this instant instead of now.",
                    "type": "string",
                    "default": "now"
                  }
                },
                "required": [
                  "expression"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/json/query": {
      "get": {
        "operationId": "json_query_get",
        "summary": "Extract values from a JSON document with a JSONPath expression.",
        "description": "Runs a JSONPath query and returns the matching values with their concrete paths. Supports property access, array indexing (including negative indices), slices, wildcards, recursive descent (`..`) and filters (`[?(@.price > 10)]`). Pull three fields out of a large API response without carrying the whole document through context.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "json",
            "in": "query",
            "required": true,
            "description": "The JSON document, as an object or a JSON string.",
            "schema": {
              "description": "The JSON document, as an object or a JSON string.",
              "maxLength": 1000000
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "JSONPath expression, e.g. \"$.items[*].id\" or \"$..author\".",
            "schema": {
              "description": "JSONPath expression, e.g. \"$.items[*].id\" or \"$..author\".",
              "type": "string",
              "maxLength": 1000,
              "examples": [
                "$.items[*].id"
              ]
            }
          },
          {
            "name": "first_only",
            "in": "query",
            "required": false,
            "description": "Return only the first match.",
            "schema": {
              "description": "Return only the first match.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "json_query_post",
        "summary": "Extract values from a JSON document with a JSONPath expression.",
        "description": "Runs a JSONPath query and returns the matching values with their concrete paths. Supports property access, array indexing (including negative indices), slices, wildcards, recursive descent (`..`) and filters (`[?(@.price > 10)]`). Pull three fields out of a large API response without carrying the whole document through context.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "json": {
                    "description": "The JSON document, as an object or a JSON string.",
                    "maxLength": 1000000
                  },
                  "path": {
                    "description": "JSONPath expression, e.g. \"$.items[*].id\" or \"$..author\".",
                    "type": "string",
                    "maxLength": 1000,
                    "examples": [
                      "$.items[*].id"
                    ]
                  },
                  "first_only": {
                    "description": "Return only the first match.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "json",
                  "path"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/json/repair": {
      "get": {
        "operationId": "json_repair_get",
        "summary": "Repair malformed JSON and pinpoint the exact line and column when it cannot be repaired.",
        "description": "Takes JSON that almost parses and makes it parse: markdown code fences, prose wrapped around the object, trailing commas, single or smart quotes, unquoted keys, Python True/False/None, comments, NaN, and brackets left open by a truncated response. Every change is reported, so the caller learns what its generator got wrong rather than silently depending on a fixer. When the input cannot be salvaged it returns the precise line, column and a caret pointing at the offending character — which is what makes the next attempt succeed instead of guessing.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "The malformed JSON text.",
            "schema": {
              "description": "The malformed JSON text.",
              "type": "string",
              "maxLength": 1000000
            }
          },
          {
            "name": "close_truncated",
            "in": "query",
            "required": false,
            "description": "Close brackets left open by a cut-off response.",
            "schema": {
              "description": "Close brackets left open by a cut-off response.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "json_repair_post",
        "summary": "Repair malformed JSON and pinpoint the exact line and column when it cannot be repaired.",
        "description": "Takes JSON that almost parses and makes it parse: markdown code fences, prose wrapped around the object, trailing commas, single or smart quotes, unquoted keys, Python True/False/None, comments, NaN, and brackets left open by a truncated response. Every change is reported, so the caller learns what its generator got wrong rather than silently depending on a fixer. When the input cannot be salvaged it returns the precise line, column and a caret pointing at the offending character — which is what makes the next attempt succeed instead of guessing.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "The malformed JSON text.",
                    "type": "string",
                    "maxLength": 1000000
                  },
                  "close_truncated": {
                    "description": "Close brackets left open by a cut-off response.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/json/canonical": {
      "get": {
        "operationId": "json_canonical_get",
        "summary": "Canonicalize JSON (RFC 8785) and content-address it with SHA-256 and a CIDv1.",
        "description": "Serializes a JSON document to its one canonical form — keys sorted, whitespace dropped, numbers in ECMAScript form — then hashes it. Two documents that mean the same thing produce the same digest regardless of key order or formatting, which is what makes the digest quotable as a receipt. A log line is a claim that the process which wrote it could also edit; a content address is computed from the content, so changing the content changes the address. Pair it with crypto.verify: canonicalize, sign the digest with your own key, and anyone can check the pair without trusting either of you.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "json",
            "in": "query",
            "required": true,
            "description": "The JSON document, as an object or a JSON string.",
            "schema": {
              "description": "The JSON document, as an object or a JSON string.",
              "maxLength": 1000000
            }
          },
          {
            "name": "include_canonical",
            "in": "query",
            "required": false,
            "description": "Include the canonical serialization itself, not just its digest.",
            "schema": {
              "description": "Include the canonical serialization itself, not just its digest.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "json_canonical_post",
        "summary": "Canonicalize JSON (RFC 8785) and content-address it with SHA-256 and a CIDv1.",
        "description": "Serializes a JSON document to its one canonical form — keys sorted, whitespace dropped, numbers in ECMAScript form — then hashes it. Two documents that mean the same thing produce the same digest regardless of key order or formatting, which is what makes the digest quotable as a receipt. A log line is a claim that the process which wrote it could also edit; a content address is computed from the content, so changing the content changes the address. Pair it with crypto.verify: canonicalize, sign the digest with your own key, and anyone can check the pair without trusting either of you.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "json": {
                    "description": "The JSON document, as an object or a JSON string.",
                    "maxLength": 1000000
                  },
                  "include_canonical": {
                    "description": "Include the canonical serialization itself, not just its digest.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "json"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/json/diff": {
      "get": {
        "operationId": "json_diff_get",
        "summary": "Structural difference between two JSON documents, as RFC 6902-style operations.",
        "description": "Compares two JSON documents key by key and reports every addition, removal and change with a JSON Pointer path. Key order and formatting are ignored, so it answers 'did the data actually change' rather than 'did the bytes change' — the right check for API responses and config drift.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "a",
            "in": "query",
            "required": true,
            "description": "First document (object or JSON string).",
            "schema": {
              "description": "First document (object or JSON string).",
              "maxLength": 1000000
            }
          },
          {
            "name": "b",
            "in": "query",
            "required": true,
            "description": "Second document (object or JSON string).",
            "schema": {
              "description": "Second document (object or JSON string).",
              "maxLength": 1000000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "json_diff_post",
        "summary": "Structural difference between two JSON documents, as RFC 6902-style operations.",
        "description": "Compares two JSON documents key by key and reports every addition, removal and change with a JSON Pointer path. Key order and formatting are ignored, so it answers 'did the data actually change' rather than 'did the bytes change' — the right check for API responses and config drift.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "a": {
                    "description": "First document (object or JSON string).",
                    "maxLength": 1000000
                  },
                  "b": {
                    "description": "Second document (object or JSON string).",
                    "maxLength": 1000000
                  }
                },
                "required": [
                  "a",
                  "b"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/json/schema": {
      "get": {
        "operationId": "json_schema_get",
        "summary": "Infer a JSON Schema from an example document.",
        "description": "Generates a draft 2020-12 JSON Schema from one or more sample documents, detecting string formats (date-time, email, uri, uuid, ipv4) and merging array members into a single item schema. Turns an undocumented API response into a contract you can validate against or hand to a typed client generator.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "json",
            "in": "query",
            "required": true,
            "description": "Sample document, or an array of samples to merge.",
            "schema": {
              "description": "Sample document, or an array of samples to merge.",
              "maxLength": 1000000
            }
          },
          {
            "name": "title",
            "in": "query",
            "required": false,
            "description": "Optional schema title.",
            "schema": {
              "description": "Optional schema title.",
              "type": "string",
              "default": ""
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "json_schema_post",
        "summary": "Infer a JSON Schema from an example document.",
        "description": "Generates a draft 2020-12 JSON Schema from one or more sample documents, detecting string formats (date-time, email, uri, uuid, ipv4) and merging array members into a single item schema. Turns an undocumented API response into a contract you can validate against or hand to a typed client generator.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "json": {
                    "description": "Sample document, or an array of samples to merge.",
                    "maxLength": 1000000
                  },
                  "title": {
                    "description": "Optional schema title.",
                    "type": "string",
                    "default": ""
                  }
                },
                "required": [
                  "json"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/api/diff": {
      "get": {
        "operationId": "api_diff_get",
        "summary": "Diff an API's declared contract against payloads it actually returned; classify the drift.",
        "description": "Answers 'is this endpoint keeping its promise' — the failure mode where docs say one thing and the live API returns another, the schema validates, and nothing errors. Give it the declared JSON Schema (or a baseline payload to infer one from) plus one or more observed payloads. Returns a verdict, the inferred observed schema, and classified findings: type_mismatch, missing_field and enum_violation (action: block), nullable_in_practice, format_mismatch, undeclared_field and extra_field (action: warn), each with a JSON Pointer path and how many samples it affected. Declared-schema keywords outside the checked subset are listed in ignored_keywords, never silently trusted. Stateless: you hold the baseline, nothing is stored.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "declared",
            "in": "query",
            "required": false,
            "description": "Declared contract: a JSON Schema (object or string). Omit to infer one from `baseline`.",
            "schema": {
              "description": "Declared contract: a JSON Schema (object or string). Omit to infer one from `baseline`.",
              "maxLength": 500000
            }
          },
          {
            "name": "baseline",
            "in": "query",
            "required": false,
            "description": "Alternative to `declared`: a known-good payload (or array of them) to infer the contract from.",
            "schema": {
              "description": "Alternative to `declared`: a known-good payload (or array of them) to infer the contract from.",
              "maxLength": 500000
            }
          },
          {
            "name": "observed",
            "in": "query",
            "required": true,
            "description": "Payload the endpoint actually returned, or an array of payloads to check together.",
            "schema": {
              "description": "Payload the endpoint actually returned, or an array of payloads to check together.",
              "maxLength": 1000000
            }
          },
          {
            "name": "samples",
            "in": "query",
            "required": false,
            "description": "Treat a top-level `observed` array as multiple samples rather than one array payload.",
            "schema": {
              "description": "Treat a top-level `observed` array as multiple samples rather than one array payload.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "api_diff_post",
        "summary": "Diff an API's declared contract against payloads it actually returned; classify the drift.",
        "description": "Answers 'is this endpoint keeping its promise' — the failure mode where docs say one thing and the live API returns another, the schema validates, and nothing errors. Give it the declared JSON Schema (or a baseline payload to infer one from) plus one or more observed payloads. Returns a verdict, the inferred observed schema, and classified findings: type_mismatch, missing_field and enum_violation (action: block), nullable_in_practice, format_mismatch, undeclared_field and extra_field (action: warn), each with a JSON Pointer path and how many samples it affected. Declared-schema keywords outside the checked subset are listed in ignored_keywords, never silently trusted. Stateless: you hold the baseline, nothing is stored.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "declared": {
                    "description": "Declared contract: a JSON Schema (object or string). Omit to infer one from `baseline`.",
                    "maxLength": 500000
                  },
                  "baseline": {
                    "description": "Alternative to `declared`: a known-good payload (or array of them) to infer the contract from.",
                    "maxLength": 500000
                  },
                  "observed": {
                    "description": "Payload the endpoint actually returned, or an array of payloads to check together.",
                    "maxLength": 1000000
                  },
                  "samples": {
                    "description": "Treat a top-level `observed` array as multiple samples rather than one array payload.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "observed"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/csv/convert": {
      "get": {
        "operationId": "csv_convert_get",
        "summary": "Convert between CSV and JSON with correct quote handling.",
        "description": "A full RFC 4180 parser: quoted fields, escaped quotes, embedded commas and newlines inside cells all survive the round trip, and the delimiter is detected automatically. Splitting CSV on commas is the classic silent data-corruption bug; this does not have it.",
        "tags": [
          "data"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "CSV text, or JSON array of objects when converting to CSV.",
            "schema": {
              "description": "CSV text, or JSON array of objects when converting to CSV.",
              "maxLength": 1000000
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "Conversion direction.",
            "schema": {
              "description": "Conversion direction.",
              "type": "string",
              "enum": [
                "csv_to_json",
                "json_to_csv"
              ],
              "default": "csv_to_json"
            }
          },
          {
            "name": "delimiter",
            "in": "query",
            "required": false,
            "description": "Field delimiter. \"auto\" detects among comma, semicolon, tab and pipe.",
            "schema": {
              "description": "Field delimiter. \"auto\" detects among comma, semicolon, tab and pipe.",
              "type": "string",
              "default": "auto",
              "maxLength": 4
            }
          },
          {
            "name": "header",
            "in": "query",
            "required": false,
            "description": "Treat the first CSV row as column names.",
            "schema": {
              "description": "Treat the first CSV row as column names.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "csv_convert_post",
        "summary": "Convert between CSV and JSON with correct quote handling.",
        "description": "A full RFC 4180 parser: quoted fields, escaped quotes, embedded commas and newlines inside cells all survive the round trip, and the delimiter is detected automatically. Splitting CSV on commas is the classic silent data-corruption bug; this does not have it.",
        "tags": [
          "data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "CSV text, or JSON array of objects when converting to CSV.",
                    "maxLength": 1000000
                  },
                  "direction": {
                    "description": "Conversion direction.",
                    "type": "string",
                    "enum": [
                      "csv_to_json",
                      "json_to_csv"
                    ],
                    "default": "csv_to_json"
                  },
                  "delimiter": {
                    "description": "Field delimiter. \"auto\" detects among comma, semicolon, tab and pipe.",
                    "type": "string",
                    "default": "auto",
                    "maxLength": 4
                  },
                  "header": {
                    "description": "Treat the first CSV row as column names.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/text/stats": {
      "get": {
        "operationId": "text_stats_get",
        "summary": "Count characters, words, bytes, sentences and estimated tokens; score readability.",
        "description": "Measures text the way a form validator, a database column and a model context window each measure it — characters, UTF-8 bytes and estimated tokens are three different numbers, and conflating them is how 'it fits' turns into a truncation bug. Also returns Flesch reading ease and Flesch-Kincaid grade level.",
        "tags": [
          "text"
        ],
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Text to measure.",
            "schema": {
              "description": "Text to measure.",
              "type": "string",
              "maxLength": 500000
            }
          },
          {
            "name": "top_words",
            "in": "query",
            "required": false,
            "description": "How many of the most frequent words to return (0 disables).",
            "schema": {
              "description": "How many of the most frequent words to return (0 disables).",
              "type": "integer",
              "default": 10,
              "minimum": 0,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "text_stats_post",
        "summary": "Count characters, words, bytes, sentences and estimated tokens; score readability.",
        "description": "Measures text the way a form validator, a database column and a model context window each measure it — characters, UTF-8 bytes and estimated tokens are three different numbers, and conflating them is how 'it fits' turns into a truncation bug. Also returns Flesch reading ease and Flesch-Kincaid grade level.",
        "tags": [
          "text"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to measure.",
                    "type": "string",
                    "maxLength": 500000
                  },
                  "top_words": {
                    "description": "How many of the most frequent words to return (0 disables).",
                    "type": "integer",
                    "default": 10,
                    "minimum": 0,
                    "maximum": 100
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/text/case": {
      "get": {
        "operationId": "text_case_get",
        "summary": "Convert a string to camelCase, snake_case, kebab-case, Title Case, a URL slug and more.",
        "description": "Splits an identifier on whatever convention it currently uses — spaces, underscores, hyphens or camel humps, including acronym runs like 'HTTPServer' — then re-emits it in every common casing at once. The slug form also strips accents and punctuation for use in URLs.",
        "tags": [
          "text"
        ],
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Input string.",
            "schema": {
              "description": "Input string.",
              "type": "string",
              "maxLength": 10000,
              "examples": [
                "hello world example"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "text_case_post",
        "summary": "Convert a string to camelCase, snake_case, kebab-case, Title Case, a URL slug and more.",
        "description": "Splits an identifier on whatever convention it currently uses — spaces, underscores, hyphens or camel humps, including acronym runs like 'HTTPServer' — then re-emits it in every common casing at once. The slug form also strips accents and punctuation for use in URLs.",
        "tags": [
          "text"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Input string.",
                    "type": "string",
                    "maxLength": 10000,
                    "examples": [
                      "hello world example"
                    ]
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/text/diff": {
      "get": {
        "operationId": "text_diff_get",
        "summary": "Unified diff between two texts, with change statistics and a similarity score.",
        "description": "Produces a git-style unified diff plus structured hunks and a similarity ratio. Compare by line for code and config, or by word to see edits inside a paragraph. Useful for confirming exactly what changed before writing a file, and for summarising a change without re-reading both versions.",
        "tags": [
          "text"
        ],
        "parameters": [
          {
            "name": "a",
            "in": "query",
            "required": true,
            "description": "Original text.",
            "schema": {
              "description": "Original text.",
              "type": "string",
              "maxLength": 200000
            }
          },
          {
            "name": "b",
            "in": "query",
            "required": true,
            "description": "Modified text.",
            "schema": {
              "description": "Modified text.",
              "type": "string",
              "maxLength": 200000
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Granularity of comparison.",
            "schema": {
              "description": "Granularity of comparison.",
              "type": "string",
              "enum": [
                "line",
                "word"
              ],
              "default": "line"
            }
          },
          {
            "name": "context",
            "in": "query",
            "required": false,
            "description": "Lines of unchanged context around each hunk.",
            "schema": {
              "description": "Lines of unchanged context around each hunk.",
              "type": "integer",
              "default": 3,
              "minimum": 0,
              "maximum": 20
            }
          },
          {
            "name": "ignore_whitespace",
            "in": "query",
            "required": false,
            "description": "Ignore leading/trailing whitespace differences.",
            "schema": {
              "description": "Ignore leading/trailing whitespace differences.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "text_diff_post",
        "summary": "Unified diff between two texts, with change statistics and a similarity score.",
        "description": "Produces a git-style unified diff plus structured hunks and a similarity ratio. Compare by line for code and config, or by word to see edits inside a paragraph. Useful for confirming exactly what changed before writing a file, and for summarising a change without re-reading both versions.",
        "tags": [
          "text"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "a": {
                    "description": "Original text.",
                    "type": "string",
                    "maxLength": 200000
                  },
                  "b": {
                    "description": "Modified text.",
                    "type": "string",
                    "maxLength": 200000
                  },
                  "mode": {
                    "description": "Granularity of comparison.",
                    "type": "string",
                    "enum": [
                      "line",
                      "word"
                    ],
                    "default": "line"
                  },
                  "context": {
                    "description": "Lines of unchanged context around each hunk.",
                    "type": "integer",
                    "default": 3,
                    "minimum": 0,
                    "maximum": 20
                  },
                  "ignore_whitespace": {
                    "description": "Ignore leading/trailing whitespace differences.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "a",
                  "b"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/regex/test": {
      "get": {
        "operationId": "regex_test_get",
        "summary": "Test a regular expression against text and inspect every match and capture group.",
        "description": "Runs a JavaScript regular expression and returns each match with its index, numbered groups and named groups — or performs a replace or split. Invalid patterns come back as a readable explanation instead of a thrown error, so a pattern can be corrected without a round trip through a broken deploy.",
        "tags": [
          "text"
        ],
        "parameters": [
          {
            "name": "pattern",
            "in": "query",
            "required": true,
            "description": "Regular expression source, without delimiters.",
            "schema": {
              "description": "Regular expression source, without delimiters.",
              "type": "string",
              "maxLength": 2000,
              "examples": [
                "\\b(\\w+)@(\\w+\\.\\w+)\\b"
              ]
            }
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Text to run the pattern against.",
            "schema": {
              "description": "Text to run the pattern against.",
              "type": "string",
              "maxLength": 200000
            }
          },
          {
            "name": "flags",
            "in": "query",
            "required": false,
            "description": "Regex flags, e.g. \"gi\". The g flag is added automatically for match_all, replace and split.",
            "schema": {
              "description": "Regex flags, e.g. \"gi\". The g flag is added automatically for match_all, replace and split.",
              "type": "string",
              "default": "g",
              "maxLength": 8
            }
          },
          {
            "name": "operation",
            "in": "query",
            "required": false,
            "description": "What to do with the pattern.",
            "schema": {
              "description": "What to do with the pattern.",
              "type": "string",
              "enum": [
                "match_all",
                "test",
                "replace",
                "split"
              ],
              "default": "match_all"
            }
          },
          {
            "name": "replacement",
            "in": "query",
            "required": false,
            "description": "Replacement string for the replace operation. Supports $1, $<name>.",
            "schema": {
              "description": "Replacement string for the replace operation. Supports $1, $<name>.",
              "type": "string",
              "default": ""
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum matches to return.",
            "schema": {
              "description": "Maximum matches to return.",
              "type": "integer",
              "default": 100,
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "regex_test_post",
        "summary": "Test a regular expression against text and inspect every match and capture group.",
        "description": "Runs a JavaScript regular expression and returns each match with its index, numbered groups and named groups — or performs a replace or split. Invalid patterns come back as a readable explanation instead of a thrown error, so a pattern can be corrected without a round trip through a broken deploy.",
        "tags": [
          "text"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "pattern": {
                    "description": "Regular expression source, without delimiters.",
                    "type": "string",
                    "maxLength": 2000,
                    "examples": [
                      "\\b(\\w+)@(\\w+\\.\\w+)\\b"
                    ]
                  },
                  "text": {
                    "description": "Text to run the pattern against.",
                    "type": "string",
                    "maxLength": 200000
                  },
                  "flags": {
                    "description": "Regex flags, e.g. \"gi\". The g flag is added automatically for match_all, replace and split.",
                    "type": "string",
                    "default": "g",
                    "maxLength": 8
                  },
                  "operation": {
                    "description": "What to do with the pattern.",
                    "type": "string",
                    "enum": [
                      "match_all",
                      "test",
                      "replace",
                      "split"
                    ],
                    "default": "match_all"
                  },
                  "replacement": {
                    "description": "Replacement string for the replace operation. Supports $1, $<name>.",
                    "type": "string",
                    "default": ""
                  },
                  "limit": {
                    "description": "Maximum matches to return.",
                    "type": "integer",
                    "default": 100,
                    "minimum": 1,
                    "maximum": 1000
                  }
                },
                "required": [
                  "pattern",
                  "text"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/hash": {
      "get": {
        "operationId": "hash_get",
        "summary": "Hash or HMAC-sign text with MD5, SHA-1, SHA-256/384/512 or CRC32.",
        "description": "Computes cryptographic digests and HMAC signatures. Returns hex and base64 at once, so a webhook signature can be compared in whichever encoding the provider uses. MD5 and CRC32 are included for checksums and legacy fixtures; they are not secure for authentication.",
        "tags": [
          "crypto"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "Text to hash.",
            "schema": {
              "description": "Text to hash.",
              "type": "string",
              "maxLength": 200000,
              "examples": [
                "hello world"
              ]
            }
          },
          {
            "name": "algorithms",
            "in": "query",
            "required": false,
            "description": "Any of: md5, sha1, sha256, sha384, sha512, crc32.",
            "schema": {
              "description": "Any of: md5, sha1, sha256, sha384, sha512, crc32.",
              "type": "array",
              "default": [
                "sha256"
              ],
              "items": {
                "type": "string"
              },
              "examples": [
                [
                  "sha256",
                  "md5"
                ]
              ]
            }
          },
          {
            "name": "hmac_key",
            "in": "query",
            "required": false,
            "description": "When set, computes HMAC-<algorithm> with this key instead of a plain digest. Not supported for md5/crc32.",
            "schema": {
              "description": "When set, computes HMAC-<algorithm> with this key instead of a plain digest. Not supported for md5/crc32.",
              "type": "string",
              "default": "",
              "maxLength": 4096
            }
          },
          {
            "name": "input_encoding",
            "in": "query",
            "required": false,
            "description": "How to read `input` into bytes.",
            "schema": {
              "description": "How to read `input` into bytes.",
              "type": "string",
              "enum": [
                "utf8",
                "hex",
                "base64"
              ],
              "default": "utf8"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "hash_post",
        "summary": "Hash or HMAC-sign text with MD5, SHA-1, SHA-256/384/512 or CRC32.",
        "description": "Computes cryptographic digests and HMAC signatures. Returns hex and base64 at once, so a webhook signature can be compared in whichever encoding the provider uses. MD5 and CRC32 are included for checksums and legacy fixtures; they are not secure for authentication.",
        "tags": [
          "crypto"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "Text to hash.",
                    "type": "string",
                    "maxLength": 200000,
                    "examples": [
                      "hello world"
                    ]
                  },
                  "algorithms": {
                    "description": "Any of: md5, sha1, sha256, sha384, sha512, crc32.",
                    "type": "array",
                    "default": [
                      "sha256"
                    ],
                    "items": {
                      "type": "string"
                    },
                    "examples": [
                      [
                        "sha256",
                        "md5"
                      ]
                    ]
                  },
                  "hmac_key": {
                    "description": "When set, computes HMAC-<algorithm> with this key instead of a plain digest. Not supported for md5/crc32.",
                    "type": "string",
                    "default": "",
                    "maxLength": 4096
                  },
                  "input_encoding": {
                    "description": "How to read `input` into bytes.",
                    "type": "string",
                    "enum": [
                      "utf8",
                      "hex",
                      "base64"
                    ],
                    "default": "utf8"
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/crypto/verify": {
      "get": {
        "operationId": "crypto_verify_get",
        "summary": "Verify an Ed25519, ECDSA, RSA or HMAC signature against a message and public key.",
        "description": "Checks a detached signature and returns a single boolean you can act on. Signature verification is not something to reason about — a signature is either valid under the key or it is not, and an agent that accepts an identity claim without checking has accepted anything. Supports Ed25519 (raw 32-byte or SPKI keys), ECDSA P-256/P-384, RSA PKCS#1 v1.5 and PSS, and HMAC-SHA256/512.",
        "tags": [
          "crypto"
        ],
        "parameters": [
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "The signed message.",
            "schema": {
              "description": "The signed message.",
              "type": "string",
              "maxLength": 200000
            }
          },
          {
            "name": "signature",
            "in": "query",
            "required": true,
            "description": "The detached signature.",
            "schema": {
              "description": "The detached signature.",
              "type": "string",
              "maxLength": 8000
            }
          },
          {
            "name": "public_key",
            "in": "query",
            "required": true,
            "description": "Public key: raw bytes, SPKI DER, or PEM. For HMAC, the shared secret.",
            "schema": {
              "description": "Public key: raw bytes, SPKI DER, or PEM. For HMAC, the shared secret.",
              "type": "string",
              "maxLength": 8000
            }
          },
          {
            "name": "algorithm",
            "in": "query",
            "required": false,
            "description": "Signature algorithm.",
            "schema": {
              "description": "Signature algorithm.",
              "type": "string",
              "enum": [
                "ed25519",
                "ecdsa-p256",
                "ecdsa-p384",
                "rsa-pkcs1",
                "rsa-pss",
                "hmac-sha256",
                "hmac-sha512"
              ],
              "default": "ed25519"
            }
          },
          {
            "name": "message_encoding",
            "in": "query",
            "required": false,
            "description": "How to read `message` into bytes.",
            "schema": {
              "description": "How to read `message` into bytes.",
              "type": "string",
              "enum": [
                "utf8",
                "hex",
                "base64"
              ],
              "default": "utf8"
            }
          },
          {
            "name": "signature_encoding",
            "in": "query",
            "required": false,
            "description": "How to read `signature` into bytes.",
            "schema": {
              "description": "How to read `signature` into bytes.",
              "type": "string",
              "enum": [
                "hex",
                "base64",
                "utf8"
              ],
              "default": "hex"
            }
          },
          {
            "name": "key_encoding",
            "in": "query",
            "required": false,
            "description": "How to read `public_key` when it is not PEM.",
            "schema": {
              "description": "How to read `public_key` when it is not PEM.",
              "type": "string",
              "enum": [
                "hex",
                "base64",
                "utf8"
              ],
              "default": "hex"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "crypto_verify_post",
        "summary": "Verify an Ed25519, ECDSA, RSA or HMAC signature against a message and public key.",
        "description": "Checks a detached signature and returns a single boolean you can act on. Signature verification is not something to reason about — a signature is either valid under the key or it is not, and an agent that accepts an identity claim without checking has accepted anything. Supports Ed25519 (raw 32-byte or SPKI keys), ECDSA P-256/P-384, RSA PKCS#1 v1.5 and PSS, and HMAC-SHA256/512.",
        "tags": [
          "crypto"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "description": "The signed message.",
                    "type": "string",
                    "maxLength": 200000
                  },
                  "signature": {
                    "description": "The detached signature.",
                    "type": "string",
                    "maxLength": 8000
                  },
                  "public_key": {
                    "description": "Public key: raw bytes, SPKI DER, or PEM. For HMAC, the shared secret.",
                    "type": "string",
                    "maxLength": 8000
                  },
                  "algorithm": {
                    "description": "Signature algorithm.",
                    "type": "string",
                    "enum": [
                      "ed25519",
                      "ecdsa-p256",
                      "ecdsa-p384",
                      "rsa-pkcs1",
                      "rsa-pss",
                      "hmac-sha256",
                      "hmac-sha512"
                    ],
                    "default": "ed25519"
                  },
                  "message_encoding": {
                    "description": "How to read `message` into bytes.",
                    "type": "string",
                    "enum": [
                      "utf8",
                      "hex",
                      "base64"
                    ],
                    "default": "utf8"
                  },
                  "signature_encoding": {
                    "description": "How to read `signature` into bytes.",
                    "type": "string",
                    "enum": [
                      "hex",
                      "base64",
                      "utf8"
                    ],
                    "default": "hex"
                  },
                  "key_encoding": {
                    "description": "How to read `public_key` when it is not PEM.",
                    "type": "string",
                    "enum": [
                      "hex",
                      "base64",
                      "utf8"
                    ],
                    "default": "hex"
                  }
                },
                "required": [
                  "message",
                  "signature",
                  "public_key"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/jwt/decode": {
      "get": {
        "operationId": "jwt_decode_get",
        "summary": "Decode a JWT and check its expiry, optionally verifying an HMAC signature.",
        "description": "Splits a JSON Web Token, decodes header and payload, and converts every standard time claim (exp, iat, nbf, auth_time) into readable dates with a live expiry verdict. Supply `secret` to verify an HS256/384/512 signature. Decoding never validates trust on its own — an unverified token is just base64 text that anyone can forge.",
        "tags": [
          "crypto"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "description": "The JWT (three base64url segments separated by dots). A leading \"Bearer \" is ignored.",
            "schema": {
              "description": "The JWT (three base64url segments separated by dots). A leading \"Bearer \" is ignored.",
              "type": "string",
              "maxLength": 100000
            }
          },
          {
            "name": "secret",
            "in": "query",
            "required": false,
            "description": "HMAC secret. When provided, the signature is verified for HS256/HS384/HS512.",
            "schema": {
              "description": "HMAC secret. When provided, the signature is verified for HS256/HS384/HS512.",
              "type": "string",
              "default": "",
              "maxLength": 4096
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "jwt_decode_post",
        "summary": "Decode a JWT and check its expiry, optionally verifying an HMAC signature.",
        "description": "Splits a JSON Web Token, decodes header and payload, and converts every standard time claim (exp, iat, nbf, auth_time) into readable dates with a live expiry verdict. Supply `secret` to verify an HS256/384/512 signature. Decoding never validates trust on its own — an unverified token is just base64 text that anyone can forge.",
        "tags": [
          "crypto"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The JWT (three base64url segments separated by dots). A leading \"Bearer \" is ignored.",
                    "type": "string",
                    "maxLength": 100000
                  },
                  "secret": {
                    "description": "HMAC secret. When provided, the signature is verified for HS256/HS384/HS512.",
                    "type": "string",
                    "default": "",
                    "maxLength": 4096
                  }
                },
                "required": [
                  "token"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/encode": {
      "get": {
        "operationId": "encode_get",
        "summary": "Convert text between base64, base64url, hex, URL and HTML encodings.",
        "description": "Round-trips a value between encodings in one call. Handles base64url (JWT-style, no padding) and distinguishes full-URI encoding from component encoding, which is the usual cause of double-encoded query strings.",
        "tags": [
          "crypto"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "Value to convert.",
            "schema": {
              "description": "Value to convert.",
              "type": "string",
              "maxLength": 500000,
              "examples": [
                "hello world"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Encoding of the input.",
            "schema": {
              "description": "Encoding of the input.",
              "type": "string",
              "enum": [
                "text",
                "base64",
                "base64url",
                "hex",
                "url",
                "url_component",
                "html"
              ],
              "default": "text"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Encoding to produce.",
            "schema": {
              "description": "Encoding to produce.",
              "type": "string",
              "enum": [
                "text",
                "base64",
                "base64url",
                "hex",
                "url",
                "url_component",
                "html"
              ],
              "default": "base64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "encode_post",
        "summary": "Convert text between base64, base64url, hex, URL and HTML encodings.",
        "description": "Round-trips a value between encodings in one call. Handles base64url (JWT-style, no padding) and distinguishes full-URI encoding from component encoding, which is the usual cause of double-encoded query strings.",
        "tags": [
          "crypto"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "Value to convert.",
                    "type": "string",
                    "maxLength": 500000,
                    "examples": [
                      "hello world"
                    ]
                  },
                  "from": {
                    "description": "Encoding of the input.",
                    "type": "string",
                    "enum": [
                      "text",
                      "base64",
                      "base64url",
                      "hex",
                      "url",
                      "url_component",
                      "html"
                    ],
                    "default": "text"
                  },
                  "to": {
                    "description": "Encoding to produce.",
                    "type": "string",
                    "enum": [
                      "text",
                      "base64",
                      "base64url",
                      "hex",
                      "url",
                      "url_component",
                      "html"
                    ],
                    "default": "base64"
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/id/generate": {
      "get": {
        "operationId": "id_generate_get",
        "summary": "Generate UUIDv4, UUIDv7, ULID, nanoid or short random IDs.",
        "description": "Cryptographically random identifiers from the edge. UUIDv7 and ULID embed a millisecond timestamp and sort lexicographically in creation order, which makes them the right default for database primary keys; UUIDv4 is fully random and does not sort. The embedded timestamp is decoded back for you.",
        "tags": [
          "crypto"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Identifier format.",
            "schema": {
              "description": "Identifier format.",
              "type": "string",
              "enum": [
                "uuid4",
                "uuid7",
                "ulid",
                "nanoid",
                "hex",
                "numeric"
              ],
              "default": "uuid4"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "How many to generate.",
            "schema": {
              "description": "How many to generate.",
              "type": "integer",
              "default": 1,
              "minimum": 1,
              "maximum": 500
            }
          },
          {
            "name": "length",
            "in": "query",
            "required": false,
            "description": "Length for nanoid, hex and numeric types.",
            "schema": {
              "description": "Length for nanoid, hex and numeric types.",
              "type": "integer",
              "default": 21,
              "minimum": 1,
              "maximum": 256
            }
          },
          {
            "name": "uppercase",
            "in": "query",
            "required": false,
            "description": "Uppercase the output where the format allows it.",
            "schema": {
              "description": "Uppercase the output where the format allows it.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "id_generate_post",
        "summary": "Generate UUIDv4, UUIDv7, ULID, nanoid or short random IDs.",
        "description": "Cryptographically random identifiers from the edge. UUIDv7 and ULID embed a millisecond timestamp and sort lexicographically in creation order, which makes them the right default for database primary keys; UUIDv4 is fully random and does not sort. The embedded timestamp is decoded back for you.",
        "tags": [
          "crypto"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "description": "Identifier format.",
                    "type": "string",
                    "enum": [
                      "uuid4",
                      "uuid7",
                      "ulid",
                      "nanoid",
                      "hex",
                      "numeric"
                    ],
                    "default": "uuid4"
                  },
                  "count": {
                    "description": "How many to generate.",
                    "type": "integer",
                    "default": 1,
                    "minimum": 1,
                    "maximum": 500
                  },
                  "length": {
                    "description": "Length for nanoid, hex and numeric types.",
                    "type": "integer",
                    "default": 21,
                    "minimum": 1,
                    "maximum": 256
                  },
                  "uppercase": {
                    "description": "Uppercase the output where the format allows it.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/math/eval": {
      "get": {
        "operationId": "math_eval_get",
        "summary": "Evaluate a mathematical expression exactly.",
        "description": "Evaluates arithmetic with correct operator precedence, parentheses, exponentiation, factorials, named variables and 30+ functions. Language models perform arithmetic by pattern-matching and quietly get long multiplications and compounding wrong; this computes the number instead of predicting it.",
        "tags": [
          "compute"
        ],
        "parameters": [
          {
            "name": "expression",
            "in": "query",
            "required": true,
            "description": "Expression to evaluate, e.g. \"(1+0.07)^30 * 1000\".",
            "schema": {
              "description": "Expression to evaluate, e.g. \"(1+0.07)^30 * 1000\".",
              "type": "string",
              "maxLength": 2000,
              "examples": [
                "sqrt(2) * 10^3"
              ]
            }
          },
          {
            "name": "variables",
            "in": "query",
            "required": false,
            "description": "Named values usable in the expression, e.g. {\"rate\": 0.07}.",
            "schema": {
              "description": "Named values usable in the expression, e.g. {\"rate\": 0.07}.",
              "type": "object",
              "default": {}
            }
          },
          {
            "name": "precision",
            "in": "query",
            "required": false,
            "description": "Decimal places to round the formatted result to.",
            "schema": {
              "description": "Decimal places to round the formatted result to.",
              "type": "integer",
              "default": 10,
              "minimum": 0,
              "maximum": 15
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "math_eval_post",
        "summary": "Evaluate a mathematical expression exactly.",
        "description": "Evaluates arithmetic with correct operator precedence, parentheses, exponentiation, factorials, named variables and 30+ functions. Language models perform arithmetic by pattern-matching and quietly get long multiplications and compounding wrong; this computes the number instead of predicting it.",
        "tags": [
          "compute"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expression": {
                    "description": "Expression to evaluate, e.g. \"(1+0.07)^30 * 1000\".",
                    "type": "string",
                    "maxLength": 2000,
                    "examples": [
                      "sqrt(2) * 10^3"
                    ]
                  },
                  "variables": {
                    "description": "Named values usable in the expression, e.g. {\"rate\": 0.07}.",
                    "type": "object",
                    "default": {}
                  },
                  "precision": {
                    "description": "Decimal places to round the formatted result to.",
                    "type": "integer",
                    "default": 10,
                    "minimum": 0,
                    "maximum": 15
                  }
                },
                "required": [
                  "expression"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/unit/convert": {
      "get": {
        "operationId": "unit_convert_get",
        "summary": "Convert between units of length, mass, temperature, data, time, speed, area, volume, pressure, energy and angle.",
        "description": "Exact unit conversion across eleven categories, using defined conversion factors rather than remembered approximations. Temperature handles offsets correctly (0°C is 32°F, not 0°F), and binary data prefixes are kept distinct from decimal ones (a GiB is not a GB).",
        "tags": [
          "compute"
        ],
        "parameters": [
          {
            "name": "value",
            "in": "query",
            "required": false,
            "description": "Quantity to convert.",
            "schema": {
              "description": "Quantity to convert.",
              "type": "number",
              "examples": [
                100
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Source unit, e.g. \"km\", \"celsius\", \"gib\".",
            "schema": {
              "description": "Source unit, e.g. \"km\", \"celsius\", \"gib\".",
              "type": "string",
              "examples": [
                "km"
              ]
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Target unit. Must be in the same category as `from`.",
            "schema": {
              "description": "Target unit. Must be in the same category as `from`.",
              "type": "string",
              "examples": [
                "mi"
              ]
            }
          },
          {
            "name": "list",
            "in": "query",
            "required": false,
            "description": "Return every supported unit grouped by category instead of converting.",
            "schema": {
              "description": "Return every supported unit grouped by category instead of converting.",
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "precision",
            "in": "query",
            "required": false,
            "description": "Decimal places in the rounded result.",
            "schema": {
              "description": "Decimal places in the rounded result.",
              "type": "integer",
              "default": 6,
              "minimum": 0,
              "maximum": 15
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "unit_convert_post",
        "summary": "Convert between units of length, mass, temperature, data, time, speed, area, volume, pressure, energy and angle.",
        "description": "Exact unit conversion across eleven categories, using defined conversion factors rather than remembered approximations. Temperature handles offsets correctly (0°C is 32°F, not 0°F), and binary data prefixes are kept distinct from decimal ones (a GiB is not a GB).",
        "tags": [
          "compute"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "description": "Quantity to convert.",
                    "type": "number",
                    "examples": [
                      100
                    ]
                  },
                  "from": {
                    "description": "Source unit, e.g. \"km\", \"celsius\", \"gib\".",
                    "type": "string",
                    "examples": [
                      "km"
                    ]
                  },
                  "to": {
                    "description": "Target unit. Must be in the same category as `from`.",
                    "type": "string",
                    "examples": [
                      "mi"
                    ]
                  },
                  "list": {
                    "description": "Return every supported unit grouped by category instead of converting.",
                    "type": "boolean",
                    "default": false
                  },
                  "precision": {
                    "description": "Decimal places in the rounded result.",
                    "type": "integer",
                    "default": 6,
                    "minimum": 0,
                    "maximum": 15
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/color/convert": {
      "get": {
        "operationId": "color_convert_get",
        "summary": "Convert a colour between hex, RGB, HSL and OKLCh, and check WCAG contrast.",
        "description": "Parses any CSS colour notation and re-emits it in every format including OKLCh. Supply `against` to get the WCAG 2.1 contrast ratio and pass/fail verdicts for normal and large text — the check that decides whether an interface is legible, computed rather than eyeballed.",
        "tags": [
          "compute"
        ],
        "parameters": [
          {
            "name": "color",
            "in": "query",
            "required": true,
            "description": "Colour in hex, rgb(), hsl(), or a CSS name.",
            "schema": {
              "description": "Colour in hex, rgb(), hsl(), or a CSS name.",
              "type": "string",
              "maxLength": 100,
              "examples": [
                "#3b82f6"
              ]
            }
          },
          {
            "name": "against",
            "in": "query",
            "required": false,
            "description": "Optional second colour to compute a WCAG contrast ratio against.",
            "schema": {
              "description": "Optional second colour to compute a WCAG contrast ratio against.",
              "type": "string",
              "default": "",
              "maxLength": 100,
              "examples": [
                "#ffffff"
              ]
            }
          },
          {
            "name": "shades",
            "in": "query",
            "required": false,
            "description": "Also return a 50-950 lightness scale built from this hue.",
            "schema": {
              "description": "Also return a 50-950 lightness scale built from this hue.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "color_convert_post",
        "summary": "Convert a colour between hex, RGB, HSL and OKLCh, and check WCAG contrast.",
        "description": "Parses any CSS colour notation and re-emits it in every format including OKLCh. Supply `against` to get the WCAG 2.1 contrast ratio and pass/fail verdicts for normal and large text — the check that decides whether an interface is legible, computed rather than eyeballed.",
        "tags": [
          "compute"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "color": {
                    "description": "Colour in hex, rgb(), hsl(), or a CSS name.",
                    "type": "string",
                    "maxLength": 100,
                    "examples": [
                      "#3b82f6"
                    ]
                  },
                  "against": {
                    "description": "Optional second colour to compute a WCAG contrast ratio against.",
                    "type": "string",
                    "default": "",
                    "maxLength": 100,
                    "examples": [
                      "#ffffff"
                    ]
                  },
                  "shades": {
                    "description": "Also return a 50-950 lightness scale built from this hue.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "color"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/url/parse": {
      "get": {
        "operationId": "url_parse_get",
        "summary": "Parse, normalise or resolve a URL and break out its query parameters.",
        "description": "Decomposes a URL into scheme, host, port, path, query and fragment, decodes every query parameter (keeping repeated keys as arrays), and reports whether the host is an IP address or an IDN. Can also resolve a relative reference against a base URL — the operation that quietly breaks scrapers and link-followers when done with string concatenation.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "URL or relative reference to parse.",
            "schema": {
              "description": "URL or relative reference to parse.",
              "type": "string",
              "maxLength": 8000,
              "examples": [
                "https://example.com/a/b?q=hello%20world&tag=x&tag=y#top"
              ]
            }
          },
          {
            "name": "base",
            "in": "query",
            "required": false,
            "description": "Base URL to resolve a relative reference against.",
            "schema": {
              "description": "Base URL to resolve a relative reference against.",
              "type": "string",
              "default": "",
              "maxLength": 8000
            }
          },
          {
            "name": "strip_tracking",
            "in": "query",
            "required": false,
            "description": "Also return the URL with utm_* and common click-tracking parameters removed.",
            "schema": {
              "description": "Also return the URL with utm_* and common click-tracking parameters removed.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "url_parse_post",
        "summary": "Parse, normalise or resolve a URL and break out its query parameters.",
        "description": "Decomposes a URL into scheme, host, port, path, query and fragment, decodes every query parameter (keeping repeated keys as arrays), and reports whether the host is an IP address or an IDN. Can also resolve a relative reference against a base URL — the operation that quietly breaks scrapers and link-followers when done with string concatenation.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "URL or relative reference to parse.",
                    "type": "string",
                    "maxLength": 8000,
                    "examples": [
                      "https://example.com/a/b?q=hello%20world&tag=x&tag=y#top"
                    ]
                  },
                  "base": {
                    "description": "Base URL to resolve a relative reference against.",
                    "type": "string",
                    "default": "",
                    "maxLength": 8000
                  },
                  "strip_tracking": {
                    "description": "Also return the URL with utm_* and common click-tracking parameters removed.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/url/scan": {
      "get": {
        "operationId": "url_scan_get",
        "summary": "Detect credentials, tokens and personal data leaking in a URL, and return a redacted version.",
        "description": "Scans a URL's query string, path, fragment and userinfo for secrets and personal data — provider API keys, JWTs, bearer tokens, private keys, high-entropy values in credential-shaped parameters, email addresses, national identifiers and Luhn-valid card numbers. A URL is the least private place to put a secret: it is written to server logs, proxy logs, browser history and Referer headers, none of which are covered by the transport encryption. Returns a redacted URL safe to paste into a log or a ticket.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "URL to scan.",
            "schema": {
              "description": "URL to scan.",
              "type": "string",
              "maxLength": 8000,
              "examples": [
                "https://api.example.com/v1/items?api_key=sk_live_4eC39HqLyjWDarjtT1zdp7dc&user=ada@example.com"
              ]
            }
          },
          {
            "name": "include_low",
            "in": "query",
            "required": false,
            "description": "Include low-severity findings such as tracking parameters.",
            "schema": {
              "description": "Include low-severity findings such as tracking parameters.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "url_scan_post",
        "summary": "Detect credentials, tokens and personal data leaking in a URL, and return a redacted version.",
        "description": "Scans a URL's query string, path, fragment and userinfo for secrets and personal data — provider API keys, JWTs, bearer tokens, private keys, high-entropy values in credential-shaped parameters, email addresses, national identifiers and Luhn-valid card numbers. A URL is the least private place to put a secret: it is written to server logs, proxy logs, browser history and Referer headers, none of which are covered by the transport encryption. Returns a redacted URL safe to paste into a log or a ticket.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "URL to scan.",
                    "type": "string",
                    "maxLength": 8000,
                    "examples": [
                      "https://api.example.com/v1/items?api_key=sk_live_4eC39HqLyjWDarjtT1zdp7dc&user=ada@example.com"
                    ]
                  },
                  "include_low": {
                    "description": "Include low-severity findings such as tracking parameters.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/secret/scan": {
      "get": {
        "operationId": "secret_scan_get",
        "summary": "Find credentials and personal data in text, and return a redacted copy safe to share.",
        "description": "Scans arbitrary text — logs, environment files, diffs, stack traces, config, command output — for provider API keys, tokens, private keys, database connection strings, credential-shaped assignments, high-entropy values, personal data and Luhn-valid card numbers. Each finding carries a line and column so it can be located, and the matched value is masked everywhere it is reported. The intended moment to call this is just before pasting output into a model, a ticket or a chat: text an agent forwards without reading is the ordinary way live credentials end up somewhere they cannot be recalled from.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Text to scan.",
            "schema": {
              "description": "Text to scan.",
              "type": "string",
              "maxLength": 500000
            }
          },
          {
            "name": "redact",
            "in": "query",
            "required": false,
            "description": "Return a copy with every finding masked.",
            "schema": {
              "description": "Return a copy with every finding masked.",
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "include_pii",
            "in": "query",
            "required": false,
            "description": "Also flag personal data such as email addresses and phone numbers.",
            "schema": {
              "description": "Also flag personal data such as email addresses and phone numbers.",
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "min_severity",
            "in": "query",
            "required": false,
            "description": "Suppress findings below this severity.",
            "schema": {
              "description": "Suppress findings below this severity.",
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "critical"
              ],
              "default": "low"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "secret_scan_post",
        "summary": "Find credentials and personal data in text, and return a redacted copy safe to share.",
        "description": "Scans arbitrary text — logs, environment files, diffs, stack traces, config, command output — for provider API keys, tokens, private keys, database connection strings, credential-shaped assignments, high-entropy values, personal data and Luhn-valid card numbers. Each finding carries a line and column so it can be located, and the matched value is masked everywhere it is reported. The intended moment to call this is just before pasting output into a model, a ticket or a chat: text an agent forwards without reading is the ordinary way live credentials end up somewhere they cannot be recalled from.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "description": "Text to scan.",
                    "type": "string",
                    "maxLength": 500000
                  },
                  "redact": {
                    "description": "Return a copy with every finding masked.",
                    "type": "boolean",
                    "default": true
                  },
                  "include_pii": {
                    "description": "Also flag personal data such as email addresses and phone numbers.",
                    "type": "boolean",
                    "default": true
                  },
                  "min_severity": {
                    "description": "Suppress findings below this severity.",
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "default": "low"
                  }
                },
                "required": [
                  "text"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/http/check": {
      "get": {
        "operationId": "http_check_get",
        "summary": "Check whether a URL is still live: status, redirect chain, and whether a citation still says what it said.",
        "description": "Resolves a URL and reports what actually happens to it — final status, the full redirect chain, content type and page title. Link rot is faster than it feels: one agent measured seven dead URLs out of 286 across fourteen days. This handles the three cases a naive checker gets wrong: an arXiv v1 to v2 redirect is a version change, not a break; a 403 is a blocked crawler, not a dead page; and a DOI can return 200 while the page behind it is now a retraction notice, which is the worst case because a simple status check passes and the reader gets something else. Response bodies are never returned — only status, headers, title and flags.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "URL to check.",
            "schema": {
              "description": "URL to check.",
              "type": "string",
              "maxLength": 4000,
              "examples": [
                "https://arxiv.org/abs/1706.03762"
              ]
            }
          },
          {
            "name": "max_redirects",
            "in": "query",
            "required": false,
            "description": "How many redirects to follow.",
            "schema": {
              "description": "How many redirects to follow.",
              "type": "integer",
              "default": 5,
              "minimum": 0,
              "maximum": 10
            }
          },
          {
            "name": "timeout_ms",
            "in": "query",
            "required": false,
            "description": "Per-request timeout in milliseconds.",
            "schema": {
              "description": "Per-request timeout in milliseconds.",
              "type": "integer",
              "default": 8000,
              "minimum": 1000,
              "maximum": 20000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "http_check_post",
        "summary": "Check whether a URL is still live: status, redirect chain, and whether a citation still says what it said.",
        "description": "Resolves a URL and reports what actually happens to it — final status, the full redirect chain, content type and page title. Link rot is faster than it feels: one agent measured seven dead URLs out of 286 across fourteen days. This handles the three cases a naive checker gets wrong: an arXiv v1 to v2 redirect is a version change, not a break; a 403 is a blocked crawler, not a dead page; and a DOI can return 200 while the page behind it is now a retraction notice, which is the worst case because a simple status check passes and the reader gets something else. Response bodies are never returned — only status, headers, title and flags.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "URL to check.",
                    "type": "string",
                    "maxLength": 4000,
                    "examples": [
                      "https://arxiv.org/abs/1706.03762"
                    ]
                  },
                  "max_redirects": {
                    "description": "How many redirects to follow.",
                    "type": "integer",
                    "default": 5,
                    "minimum": 0,
                    "maximum": 10
                  },
                  "timeout_ms": {
                    "description": "Per-request timeout in milliseconds.",
                    "type": "integer",
                    "default": 8000,
                    "minimum": 1000,
                    "maximum": 20000
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/http/assert": {
      "get": {
        "operationId": "http_assert_get",
        "summary": "Verify a URL actually returns what you expected — status, headers, JSON values — and return a pass/fail proof.",
        "description": "The difference between an agent believing it succeeded and knowing it did. http.check tells you a URL is alive; this tells you it is correct. Assert the status, response headers, values at JSONPath expressions, substrings in the body and a latency ceiling, and get back one boolean plus a per-check breakdown showing expected against actual. An agent that has just deployed, migrated or reconfigured something can prove the outcome rather than reporting the absence of an error, which is the usual way agents claim a success they have not actually achieved.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "URL to call.",
            "schema": {
              "description": "URL to call.",
              "type": "string",
              "maxLength": 4000,
              "examples": [
                "https://fluentedi.com/health"
              ]
            }
          },
          {
            "name": "method",
            "in": "query",
            "required": false,
            "description": "HTTP method.",
            "schema": {
              "description": "HTTP method.",
              "type": "string",
              "enum": [
                "GET",
                "HEAD",
                "POST",
                "PUT",
                "PATCH",
                "DELETE",
                "OPTIONS"
              ],
              "default": "GET"
            }
          },
          {
            "name": "body",
            "in": "query",
            "required": false,
            "description": "Request body for POST, PUT and PATCH.",
            "schema": {
              "description": "Request body for POST, PUT and PATCH.",
              "type": "string",
              "default": "",
              "maxLength": 100000
            }
          },
          {
            "name": "headers",
            "in": "query",
            "required": false,
            "description": "Request headers to send.",
            "schema": {
              "description": "Request headers to send.",
              "type": "object",
              "default": {}
            }
          },
          {
            "name": "expect_status",
            "in": "query",
            "required": false,
            "description": "Required status: a number, an array of acceptable numbers, or a class such as \"2xx\".",
            "schema": {
              "description": "Required status: a number, an array of acceptable numbers, or a class such as \"2xx\".",
              "default": ""
            }
          },
          {
            "name": "expect_headers",
            "in": "query",
            "required": false,
            "description": "Response headers that must exist and contain a substring, e.g. {\"content-type\":\"json\"}.",
            "schema": {
              "description": "Response headers that must exist and contain a substring, e.g. {\"content-type\":\"json\"}.",
              "type": "object",
              "default": {}
            }
          },
          {
            "name": "expect_json",
            "in": "query",
            "required": false,
            "description": "JSONPath expressions mapped to required values, e.g. {\"$.status\":\"ok\",\"$.items[0].id\":1}.",
            "schema": {
              "description": "JSONPath expressions mapped to required values, e.g. {\"$.status\":\"ok\",\"$.items[0].id\":1}.",
              "type": "object",
              "default": {}
            }
          },
          {
            "name": "expect_body_contains",
            "in": "query",
            "required": false,
            "description": "Substrings that must appear in the body.",
            "schema": {
              "description": "Substrings that must appear in the body.",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "max_response_ms",
            "in": "query",
            "required": false,
            "description": "Fail if the response takes longer than this. 0 disables the check.",
            "schema": {
              "description": "Fail if the response takes longer than this. 0 disables the check.",
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 30000
            }
          },
          {
            "name": "timeout_ms",
            "in": "query",
            "required": false,
            "description": "Request timeout.",
            "schema": {
              "description": "Request timeout.",
              "type": "integer",
              "default": 10000,
              "minimum": 1000,
              "maximum": 30000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "http_assert_post",
        "summary": "Verify a URL actually returns what you expected — status, headers, JSON values — and return a pass/fail proof.",
        "description": "The difference between an agent believing it succeeded and knowing it did. http.check tells you a URL is alive; this tells you it is correct. Assert the status, response headers, values at JSONPath expressions, substrings in the body and a latency ceiling, and get back one boolean plus a per-check breakdown showing expected against actual. An agent that has just deployed, migrated or reconfigured something can prove the outcome rather than reporting the absence of an error, which is the usual way agents claim a success they have not actually achieved.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "URL to call.",
                    "type": "string",
                    "maxLength": 4000,
                    "examples": [
                      "https://fluentedi.com/health"
                    ]
                  },
                  "method": {
                    "description": "HTTP method.",
                    "type": "string",
                    "enum": [
                      "GET",
                      "HEAD",
                      "POST",
                      "PUT",
                      "PATCH",
                      "DELETE",
                      "OPTIONS"
                    ],
                    "default": "GET"
                  },
                  "body": {
                    "description": "Request body for POST, PUT and PATCH.",
                    "type": "string",
                    "default": "",
                    "maxLength": 100000
                  },
                  "headers": {
                    "description": "Request headers to send.",
                    "type": "object",
                    "default": {}
                  },
                  "expect_status": {
                    "description": "Required status: a number, an array of acceptable numbers, or a class such as \"2xx\".",
                    "default": ""
                  },
                  "expect_headers": {
                    "description": "Response headers that must exist and contain a substring, e.g. {\"content-type\":\"json\"}.",
                    "type": "object",
                    "default": {}
                  },
                  "expect_json": {
                    "description": "JSONPath expressions mapped to required values, e.g. {\"$.status\":\"ok\",\"$.items[0].id\":1}.",
                    "type": "object",
                    "default": {}
                  },
                  "expect_body_contains": {
                    "description": "Substrings that must appear in the body.",
                    "type": "array",
                    "default": [],
                    "items": {
                      "type": "string"
                    }
                  },
                  "max_response_ms": {
                    "description": "Fail if the response takes longer than this. 0 disables the check.",
                    "type": "integer",
                    "default": 0,
                    "minimum": 0,
                    "maximum": 30000
                  },
                  "timeout_ms": {
                    "description": "Request timeout.",
                    "type": "integer",
                    "default": 10000,
                    "minimum": 1000,
                    "maximum": 30000
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/dns/lookup": {
      "get": {
        "operationId": "dns_lookup_get",
        "summary": "Resolve DNS records (A, AAAA, MX, TXT, NS, CNAME, SOA, CAA and more).",
        "description": "Queries public DNS over HTTPS and returns parsed records with their TTLs. Confirm where a domain actually points, read SPF/DKIM/DMARC policies out of TXT records, or check mail routing — live facts that no training corpus can supply because they change without notice.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Domain name to resolve.",
            "schema": {
              "description": "Domain name to resolve.",
              "type": "string",
              "maxLength": 253,
              "examples": [
                "example.com"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "DNS record type.",
            "schema": {
              "description": "DNS record type.",
              "type": "string",
              "enum": [
                "A",
                "AAAA",
                "CNAME",
                "MX",
                "TXT",
                "NS",
                "SOA",
                "CAA",
                "SRV",
                "PTR",
                "DNSKEY",
                "DS"
              ],
              "default": "A"
            }
          },
          {
            "name": "dnssec",
            "in": "query",
            "required": false,
            "description": "Request DNSSEC validation.",
            "schema": {
              "description": "Request DNSSEC validation.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "dns_lookup_post",
        "summary": "Resolve DNS records (A, AAAA, MX, TXT, NS, CNAME, SOA, CAA and more).",
        "description": "Queries public DNS over HTTPS and returns parsed records with their TTLs. Confirm where a domain actually points, read SPF/DKIM/DMARC policies out of TXT records, or check mail routing — live facts that no training corpus can supply because they change without notice.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Domain name to resolve.",
                    "type": "string",
                    "maxLength": 253,
                    "examples": [
                      "example.com"
                    ]
                  },
                  "type": {
                    "description": "DNS record type.",
                    "type": "string",
                    "enum": [
                      "A",
                      "AAAA",
                      "CNAME",
                      "MX",
                      "TXT",
                      "NS",
                      "SOA",
                      "CAA",
                      "SRV",
                      "PTR",
                      "DNSKEY",
                      "DS"
                    ],
                    "default": "A"
                  },
                  "dnssec": {
                    "description": "Request DNSSEC validation.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/net/inspect": {
      "get": {
        "operationId": "net_inspect_get",
        "summary": "Report the caller's IP, geolocation, network and TLS details as seen from the edge.",
        "description": "Returns what a server actually observes about the caller: source IP, country and city, ASN and network operator, the Cloudflare edge location that served the request, HTTP version and TLS cipher. Useful for confirming egress IP, diagnosing a geo-routing problem, or establishing an agent's own network context.",
        "tags": [
          "web"
        ],
        "parameters": [
          {
            "name": "include_headers",
            "in": "query",
            "required": false,
            "description": "Echo the request headers back (Authorization and Cookie are redacted).",
            "schema": {
              "description": "Echo the request headers back (Authorization and Cookie are redacted).",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "net_inspect_post",
        "summary": "Report the caller's IP, geolocation, network and TLS details as seen from the edge.",
        "description": "Returns what a server actually observes about the caller: source IP, country and city, ASN and network operator, the Cloudflare edge location that served the request, HTTP version and TLS cipher. Useful for confirming egress IP, diagnosing a geo-routing problem, or establishing an agent's own network context.",
        "tags": [
          "web"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "include_headers": {
                    "description": "Echo the request headers back (Authorization and Cookie are redacted).",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/edi/parse": {
      "get": {
        "operationId": "edi_parse_get",
        "summary": "Parse an X12 EDI document (850, 856, 810, 855, 997 and others) into structured JSON.",
        "description": "Reads a raw ASC X12 interchange and returns it as JSON: delimiters taken from the ISA header, the ISA/GS/ST envelope decoded, every segment split into named elements, and a document-specific summary - purchase order lines for an 850, the HL shipment hierarchy and SSCCs for an 856, invoice totals for an 810. EDI is positional and delimiter-sensitive, and unreadable without a spec table; reading it by inspection produces confident nonsense, which is why this is a tool rather than a prompt.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "Raw X12 EDI text, beginning with ISA where available.",
            "schema": {
              "description": "Raw X12 EDI text, beginning with ISA where available.",
              "type": "string",
              "maxLength": 2000000
            }
          },
          {
            "name": "include_segments",
            "in": "query",
            "required": false,
            "description": "Include the flat segment list alongside the summary.",
            "schema": {
              "description": "Include the flat segment list alongside the summary.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "edi_parse_post",
        "summary": "Parse an X12 EDI document (850, 856, 810, 855, 997 and others) into structured JSON.",
        "description": "Reads a raw ASC X12 interchange and returns it as JSON: delimiters taken from the ISA header, the ISA/GS/ST envelope decoded, every segment split into named elements, and a document-specific summary - purchase order lines for an 850, the HL shipment hierarchy and SSCCs for an 856, invoice totals for an 810. EDI is positional and delimiter-sensitive, and unreadable without a spec table; reading it by inspection produces confident nonsense, which is why this is a tool rather than a prompt.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "Raw X12 EDI text, beginning with ISA where available.",
                    "type": "string",
                    "maxLength": 2000000
                  },
                  "include_segments": {
                    "description": "Include the flat segment list alongside the summary.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/edi/validate": {
      "get": {
        "operationId": "edi_validate_get",
        "summary": "Check an X12 document's envelope integrity and 856 HL hierarchy for the errors that cause rejections.",
        "description": "Runs the structural checks a trading partner runs before rejecting a file: control numbers matching between the ISA/IEA, GS/GE and ST/SE header and trailer pairs, declared counts matching actual counts, and - for an 856 - the HL hierarchy. HL faults are the usual cause of ASN rejections and chargebacks: a parent ID naming no existing node, a duplicate HL01, an unknown level code, a missing carton level. Every finding names the segment and states what the value should have been.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "Raw X12 EDI text.",
            "schema": {
              "description": "Raw X12 EDI text.",
              "type": "string",
              "maxLength": 2000000
            }
          },
          {
            "name": "require_levels",
            "in": "query",
            "required": false,
            "description": "HL level codes that must be present in an 856, e.g. [\"S\",\"O\",\"P\",\"I\"] for a pack-level ASN.",
            "schema": {
              "description": "HL level codes that must be present in an 856, e.g. [\"S\",\"O\",\"P\",\"I\"] for a pack-level ASN.",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "edi_validate_post",
        "summary": "Check an X12 document's envelope integrity and 856 HL hierarchy for the errors that cause rejections.",
        "description": "Runs the structural checks a trading partner runs before rejecting a file: control numbers matching between the ISA/IEA, GS/GE and ST/SE header and trailer pairs, declared counts matching actual counts, and - for an 856 - the HL hierarchy. HL faults are the usual cause of ASN rejections and chargebacks: a parent ID naming no existing node, a duplicate HL01, an unknown level code, a missing carton level. Every finding names the segment and states what the value should have been.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "Raw X12 EDI text.",
                    "type": "string",
                    "maxLength": 2000000
                  },
                  "require_levels": {
                    "description": "HL level codes that must be present in an 856, e.g. [\"S\",\"O\",\"P\",\"I\"] for a pack-level ASN.",
                    "type": "array",
                    "default": [],
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/edi/build": {
      "get": {
        "operationId": "edi_build_get",
        "summary": "Generate a valid X12 856 ASN or 850 purchase order from JSON, with correct HL pointers and envelope counts.",
        "description": "Compiles structured JSON into standards-valid X12. The parts that get documents rejected are exactly the parts a language model cannot hold in its head: the 856 hierarchy needs sequential HL IDs where every level names its parent's ID, and on a multi-carton, multi-SKU shipment that bookkeeping goes wrong silently. The ISA header is fixed-width — 106 characters exactly, every element space-padded to size — and one character out crashes the receiver's translator. Segment counts in SE01, CTT01, GE01 and IEA01 must agree with what was actually emitted. All of that is computed here rather than written by hand.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "document",
            "in": "query",
            "required": false,
            "description": "Transaction set to build.",
            "schema": {
              "description": "Transaction set to build.",
              "type": "string",
              "enum": [
                "856",
                "850"
              ],
              "default": "856"
            }
          },
          {
            "name": "data",
            "in": "query",
            "required": true,
            "description": "Document content. For 856: {shipment_id, ship_date, orders:[{po_number, packs:[{sscc, items:[{upc, quantity, unit}]}]}], parties:[{role,name,id}]}. For 850: {po_number, order_date, lines:[{quantity, unit, unit_price, upc, description}], parties:[...]}.",
            "schema": {
              "description": "Document content. For 856: {shipment_id, ship_date, orders:[{po_number, packs:[{sscc, items:[{upc, quantity, unit}]}]}], parties:[{role,name,id}]}. For 850: {po_number, order_date, lines:[{quantity, unit, unit_price, upc, description}], parties:[...]}.",
              "type": "object"
            }
          },
          {
            "name": "sender_id",
            "in": "query",
            "required": false,
            "description": "ISA06 sender identifier.",
            "schema": {
              "description": "ISA06 sender identifier.",
              "type": "string",
              "default": "SENDER",
              "maxLength": 15
            }
          },
          {
            "name": "receiver_id",
            "in": "query",
            "required": false,
            "description": "ISA08 receiver identifier.",
            "schema": {
              "description": "ISA08 receiver identifier.",
              "type": "string",
              "default": "RECEIVER",
              "maxLength": 15
            }
          },
          {
            "name": "sender_qualifier",
            "in": "query",
            "required": false,
            "description": "ISA05 qualifier, e.g. ZZ, 01 (DUNS), 12 (phone).",
            "schema": {
              "description": "ISA05 qualifier, e.g. ZZ, 01 (DUNS), 12 (phone).",
              "type": "string",
              "default": "ZZ",
              "maxLength": 2
            }
          },
          {
            "name": "receiver_qualifier",
            "in": "query",
            "required": false,
            "description": "ISA07 qualifier.",
            "schema": {
              "description": "ISA07 qualifier.",
              "type": "string",
              "default": "ZZ",
              "maxLength": 2
            }
          },
          {
            "name": "control_number",
            "in": "query",
            "required": false,
            "description": "Interchange control number (ISA13). Also seeds GS06 and ST02.",
            "schema": {
              "description": "Interchange control number (ISA13). Also seeds GS06 and ST02.",
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "test_indicator",
            "in": "query",
            "required": false,
            "description": "Mark the interchange as test (ISA15 = T) rather than production (P).",
            "schema": {
              "description": "Mark the interchange as test (ISA15 = T) rather than production (P).",
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "timestamp",
            "in": "query",
            "required": false,
            "description": "ISO instant for the envelope date/time. Defaults to now.",
            "schema": {
              "description": "ISO instant for the envelope date/time. Defaults to now.",
              "type": "string",
              "default": ""
            }
          },
          {
            "name": "include_envelope",
            "in": "query",
            "required": false,
            "description": "Wrap the transaction set in ISA/GS ... GE/IEA.",
            "schema": {
              "description": "Wrap the transaction set in ISA/GS ... GE/IEA.",
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "edi_build_post",
        "summary": "Generate a valid X12 856 ASN or 850 purchase order from JSON, with correct HL pointers and envelope counts.",
        "description": "Compiles structured JSON into standards-valid X12. The parts that get documents rejected are exactly the parts a language model cannot hold in its head: the 856 hierarchy needs sequential HL IDs where every level names its parent's ID, and on a multi-carton, multi-SKU shipment that bookkeeping goes wrong silently. The ISA header is fixed-width — 106 characters exactly, every element space-padded to size — and one character out crashes the receiver's translator. Segment counts in SE01, CTT01, GE01 and IEA01 must agree with what was actually emitted. All of that is computed here rather than written by hand.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "document": {
                    "description": "Transaction set to build.",
                    "type": "string",
                    "enum": [
                      "856",
                      "850"
                    ],
                    "default": "856"
                  },
                  "data": {
                    "description": "Document content. For 856: {shipment_id, ship_date, orders:[{po_number, packs:[{sscc, items:[{upc, quantity, unit}]}]}], parties:[{role,name,id}]}. For 850: {po_number, order_date, lines:[{quantity, unit, unit_price, upc, description}], parties:[...]}.",
                    "type": "object"
                  },
                  "sender_id": {
                    "description": "ISA06 sender identifier.",
                    "type": "string",
                    "default": "SENDER",
                    "maxLength": 15
                  },
                  "receiver_id": {
                    "description": "ISA08 receiver identifier.",
                    "type": "string",
                    "default": "RECEIVER",
                    "maxLength": 15
                  },
                  "sender_qualifier": {
                    "description": "ISA05 qualifier, e.g. ZZ, 01 (DUNS), 12 (phone).",
                    "type": "string",
                    "default": "ZZ",
                    "maxLength": 2
                  },
                  "receiver_qualifier": {
                    "description": "ISA07 qualifier.",
                    "type": "string",
                    "default": "ZZ",
                    "maxLength": 2
                  },
                  "control_number": {
                    "description": "Interchange control number (ISA13). Also seeds GS06 and ST02.",
                    "type": "integer",
                    "default": 1,
                    "minimum": 1
                  },
                  "test_indicator": {
                    "description": "Mark the interchange as test (ISA15 = T) rather than production (P).",
                    "type": "boolean",
                    "default": true
                  },
                  "timestamp": {
                    "description": "ISO instant for the envelope date/time. Defaults to now.",
                    "type": "string",
                    "default": ""
                  },
                  "include_envelope": {
                    "description": "Wrap the transaction set in ISA/GS ... GE/IEA.",
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "data"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/edi/acknowledge": {
      "get": {
        "operationId": "edi_acknowledge_get",
        "summary": "Read a 997 or 999 acknowledgment and say which documents were accepted, which were rejected, and why.",
        "description": "Decodes a Functional Acknowledgment into an answer rather than a code. A 997 reports its verdict as bare letters and numbers — AK5 of R with error 5, AK3 of 7, AK4 element 2 code 7 — which say nothing without a code table. This resolves every one into plain language, points at the failing segment position and element, and, if you supply the control numbers you sent, reconciles them so you can see what was acknowledged, what was rejected, and what never came back at all. Silence is the failure mode that costs money: an unacknowledged document is not a delivered one.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "input",
            "in": "query",
            "required": true,
            "description": "Raw 997 or 999 acknowledgment text.",
            "schema": {
              "description": "Raw 997 or 999 acknowledgment text.",
              "type": "string",
              "maxLength": 500000
            }
          },
          {
            "name": "sent",
            "in": "query",
            "required": false,
            "description": "Transaction set control numbers you sent (ST02 values), to reconcile against. e.g. [\"0001\",\"0002\"].",
            "schema": {
              "description": "Transaction set control numbers you sent (ST02 values), to reconcile against. e.g. [\"0001\",\"0002\"].",
              "type": "array",
              "default": [],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "edi_acknowledge_post",
        "summary": "Read a 997 or 999 acknowledgment and say which documents were accepted, which were rejected, and why.",
        "description": "Decodes a Functional Acknowledgment into an answer rather than a code. A 997 reports its verdict as bare letters and numbers — AK5 of R with error 5, AK3 of 7, AK4 element 2 code 7 — which say nothing without a code table. This resolves every one into plain language, points at the failing segment position and element, and, if you supply the control numbers you sent, reconciles them so you can see what was acknowledged, what was rejected, and what never came back at all. Silence is the failure mode that costs money: an unacknowledged document is not a delivered one.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "input": {
                    "description": "Raw 997 or 999 acknowledgment text.",
                    "type": "string",
                    "maxLength": 500000
                  },
                  "sent": {
                    "description": "Transaction set control numbers you sent (ST02 values), to reconcile against. e.g. [\"0001\",\"0002\"].",
                    "type": "array",
                    "default": [],
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "input"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/gs1/checkdigit": {
      "get": {
        "operationId": "gs1_checkdigit_get",
        "summary": "Calculate or validate a GS1 mod-10 check digit for SSCC-18, GTIN-14/13/12/8 and UPC.",
        "description": "Computes the GS1 mod-10 check digit, or validates a complete code and says what the digit should have been. Also catches the failure behind most real-world barcode and ASN mismatches: a spreadsheet dropping leading zeros or rendering the identifier in scientific notation, silently changing it. Pass a full code to validate, or the payload without its final digit to compute one.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "description": "The code, with or without its check digit. Spaces and hyphens are ignored.",
            "schema": {
              "description": "The code, with or without its check digit. Spaces and hyphens are ignored.",
              "type": "string",
              "maxLength": 64,
              "examples": [
                "00614141123456789"
              ]
            }
          },
          {
            "name": "length",
            "in": "query",
            "required": false,
            "description": "Expected total length (8, 12, 13, 14 or 18). Inferred when omitted.",
            "schema": {
              "description": "Expected total length (8, 12, 13, 14 or 18). Inferred when omitted.",
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "gs1_checkdigit_post",
        "summary": "Calculate or validate a GS1 mod-10 check digit for SSCC-18, GTIN-14/13/12/8 and UPC.",
        "description": "Computes the GS1 mod-10 check digit, or validates a complete code and says what the digit should have been. Also catches the failure behind most real-world barcode and ASN mismatches: a spreadsheet dropping leading zeros or rendering the identifier in scientific notation, silently changing it. Pass a full code to validate, or the payload without its final digit to compute one.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "description": "The code, with or without its check digit. Spaces and hyphens are ignored.",
                    "type": "string",
                    "maxLength": 64,
                    "examples": [
                      "00614141123456789"
                    ]
                  },
                  "length": {
                    "description": "Expected total length (8, 12, 13, 14 or 18). Inferred when omitted.",
                    "type": "integer",
                    "default": 0
                  }
                },
                "required": [
                  "code"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/id/validate": {
      "get": {
        "operationId": "id_validate_get",
        "summary": "Validate an identifier's checksum: IBAN, card, ISBN, ISSN, ISIN, CUSIP, LEI, routing number, IMEI, ORCID, GTIN, VIN, GSTIN and more.",
        "description": "Runs the real check algorithm for twenty-odd identifier schemes and says both whether it passes and what passing does not prove — which is usually the more useful half. A valid IBAN checksum does not mean the account exists; a lapsed LEI passes forever; one in ten random digit strings satisfies Luhn. Schemes with no checksum at all (BIC, IFSC, DOI, and India's PAN, whose algorithm has never been published) are reported as structure-only rather than dressed up as verified. Pass `scheme` or let it infer from shape.",
        "tags": [
          "edi"
        ],
        "parameters": [
          {
            "name": "value",
            "in": "query",
            "required": true,
            "description": "The identifier to check. Spaces, hyphens and dots are ignored.",
            "schema": {
              "description": "The identifier to check. Spaces, hyphens and dots are ignored.",
              "type": "string",
              "maxLength": 200,
              "examples": [
                "GB82WEST12345698765432"
              ]
            }
          },
          {
            "name": "scheme",
            "in": "query",
            "required": false,
            "description": "Which scheme to apply. \"auto\" infers it from the shape.",
            "schema": {
              "description": "Which scheme to apply. \"auto\" infers it from the shape.",
              "type": "string",
              "enum": [
                "auto",
                "iban",
                "card",
                "luhn",
                "isbn",
                "isbn10",
                "isbn13",
                "issn",
                "isin",
                "cusip",
                "lei",
                "aba",
                "imei",
                "orcid",
                "isni",
                "ean8",
                "ean13",
                "gtin",
                "upce",
                "vin",
                "gstin",
                "pan",
                "ifsc",
                "bic",
                "doi",
                "verhoeff"
              ],
              "default": "auto"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "id_validate_post",
        "summary": "Validate an identifier's checksum: IBAN, card, ISBN, ISSN, ISIN, CUSIP, LEI, routing number, IMEI, ORCID, GTIN, VIN, GSTIN and more.",
        "description": "Runs the real check algorithm for twenty-odd identifier schemes and says both whether it passes and what passing does not prove — which is usually the more useful half. A valid IBAN checksum does not mean the account exists; a lapsed LEI passes forever; one in ten random digit strings satisfies Luhn. Schemes with no checksum at all (BIC, IFSC, DOI, and India's PAN, whose algorithm has never been published) are reported as structure-only rather than dressed up as verified. Pass `scheme` or let it infer from shape.",
        "tags": [
          "edi"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "description": "The identifier to check. Spaces, hyphens and dots are ignored.",
                    "type": "string",
                    "maxLength": 200,
                    "examples": [
                      "GB82WEST12345698765432"
                    ]
                  },
                  "scheme": {
                    "description": "Which scheme to apply. \"auto\" infers it from the shape.",
                    "type": "string",
                    "enum": [
                      "auto",
                      "iban",
                      "card",
                      "luhn",
                      "isbn",
                      "isbn10",
                      "isbn13",
                      "issn",
                      "isin",
                      "cusip",
                      "lei",
                      "aba",
                      "imei",
                      "orcid",
                      "isni",
                      "ean8",
                      "ean13",
                      "gtin",
                      "upce",
                      "vin",
                      "gstin",
                      "pan",
                      "ifsc",
                      "bic",
                      "doi",
                      "verhoeff"
                    ],
                    "default": "auto"
                  }
                },
                "required": [
                  "value"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/tool/search": {
      "get": {
        "operationId": "tool_search_get",
        "summary": "Find the right tool for a task by describing it in plain language.",
        "description": "Searches every tool by name, summary, description and keywords, and returns the closest matches with their endpoints and parameters. Use this instead of loading the whole catalogue: describe the job (\"check whether a shipment is late\", \"fix broken JSON\", \"validate a barcode check digit\") and call what comes back. Each result says why it matched, so a wrong match is obvious rather than plausible.",
        "tags": [
          "meta"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "What you are trying to do, in plain language.",
            "schema": {
              "description": "What you are trying to do, in plain language.",
              "type": "string",
              "maxLength": 300,
              "examples": [
                "check if a date falls inside a shipping window"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum matches to return.",
            "schema": {
              "description": "Maximum matches to return.",
              "type": "integer",
              "default": 5,
              "minimum": 1,
              "maximum": 25
            }
          },
          {
            "name": "detail",
            "in": "query",
            "required": false,
            "description": "Include full parameter schemas and worked examples for each match.",
            "schema": {
              "description": "Include full parameter schemas and worked examples for each match.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "tool_search_post",
        "summary": "Find the right tool for a task by describing it in plain language.",
        "description": "Searches every tool by name, summary, description and keywords, and returns the closest matches with their endpoints and parameters. Use this instead of loading the whole catalogue: describe the job (\"check whether a shipment is late\", \"fix broken JSON\", \"validate a barcode check digit\") and call what comes back. Each result says why it matched, so a wrong match is obvious rather than plausible.",
        "tags": [
          "meta"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "q": {
                    "description": "What you are trying to do, in plain language.",
                    "type": "string",
                    "maxLength": 300,
                    "examples": [
                      "check if a date falls inside a shipping window"
                    ]
                  },
                  "limit": {
                    "description": "Maximum matches to return.",
                    "type": "integer",
                    "default": 5,
                    "minimum": 1,
                    "maximum": 25
                  },
                  "detail": {
                    "description": "Include full parameter schemas and worked examples for each match.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "q"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/tool/describe": {
      "get": {
        "operationId": "tool_describe_get",
        "summary": "Get the full parameter schema and worked examples for one tool.",
        "description": "Returns everything needed to call a tool correctly: its complete JSON Schema, every parameter with type and default, and examples known to work. Pair it with tool.search — search to find the name, describe to learn the shape, then call. This exists so the catalogue does not have to be loaded into context up front.",
        "tags": [
          "meta"
        ],
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Tool name, e.g. \"time.window\". Underscores and slashes are accepted too.",
            "schema": {
              "description": "Tool name, e.g. \"time.window\". Underscores and slashes are accepted too.",
              "type": "string",
              "maxLength": 100,
              "examples": [
                "time.window"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "tool_describe_post",
        "summary": "Get the full parameter schema and worked examples for one tool.",
        "description": "Returns everything needed to call a tool correctly: its complete JSON Schema, every parameter with type and default, and examples known to work. Pair it with tool.search — search to find the name, describe to learn the shape, then call. This exists so the catalogue does not have to be loaded into context up front.",
        "tags": [
          "meta"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "Tool name, e.g. \"time.window\". Underscores and slashes are accepted too.",
                    "type": "string",
                    "maxLength": 100,
                    "examples": [
                      "time.window"
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/tool/call": {
      "get": {
        "operationId": "tool_call_get",
        "summary": "Invoke any tool by name, including ones not in the default listing.",
        "description": "Dispatches to any tool in the catalogue. Most clients cap how many tools they will hold at once — Cursor drops everything past roughly forty across all servers combined — so only a core set is listed by default. Everything else is reachable here. Find a name with tool.search, check its shape with tool.describe, then call it through this.",
        "tags": [
          "meta"
        ],
        "parameters": [
          {
            "name": "tool",
            "in": "query",
            "required": true,
            "description": "Name of the tool to invoke.",
            "schema": {
              "description": "Name of the tool to invoke.",
              "type": "string",
              "maxLength": 100,
              "examples": [
                "gs1.checkdigit"
              ]
            }
          },
          {
            "name": "args",
            "in": "query",
            "required": false,
            "description": "Arguments for that tool.",
            "schema": {
              "description": "Arguments for that tool.",
              "type": "object",
              "default": {}
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      },
      "post": {
        "operationId": "tool_call_post",
        "summary": "Invoke any tool by name, including ones not in the default listing.",
        "description": "Dispatches to any tool in the catalogue. Most clients cap how many tools they will hold at once — Cursor drops everything past roughly forty across all servers combined — so only a core set is listed by default. Everything else is reachable here. Find a name with tool.search, check its shape with tool.describe, then call it through this.",
        "tags": [
          "meta"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tool": {
                    "description": "Name of the tool to invoke.",
                    "type": "string",
                    "maxLength": 100,
                    "examples": [
                      "gs1.checkdigit"
                    ]
                  },
                  "args": {
                    "description": "Arguments for that tool.",
                    "type": "object",
                    "default": {}
                  }
                },
                "required": [
                  "tool"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "tool": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object",
                      "description": "Tool-specific result payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. The body carries the parameter schema and working examples."
          }
        }
      }
    },
    "/v1/batch": {
      "post": {
        "operationId": "batch",
        "summary": "Run up to 20 tool calls in a single request.",
        "description": "Each call is executed independently; one failure does not abort the others.",
        "tags": [
          "meta"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "calls"
                ],
                "properties": {
                  "calls": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "object",
                      "required": [
                        "tool"
                      ],
                      "properties": {
                        "tool": {
                          "type": "string"
                        },
                        "args": {
                          "type": "object"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result object per call, in order."
          }
        }
      }
    }
  }
}