{
  "openapi": "3.1.1",
  "info": {
    "title": "Codeharbor API",
    "version": "1.0.0",
    "summary": "Deterministic tools for people and AI agents.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://codeharbor.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/tools": {
      "get": {
        "operationId": "listTools",
        "summary": "Catalog of all tools",
        "responses": {
          "200": {
            "description": "Tool list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/{id}": {
      "get": {
        "operationId": "getTool",
        "summary": "Definition of one tool",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "codeharbor-format",
                "codeharbor-diff",
                "codeharbor-markdown-preview"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/codeharbor-format/calculate": {
      "post": {
        "operationId": "calculateCodeharborFormat",
        "summary": "Format JSON, CSS and HTML and find syntax errors in JSON, YAML, JavaScript and TypeScript.",
        "description": "Paste code to re-indent JSON, CSS or HTML and to list syntax problems with line and column: JSON is parsed strictly, YAML with a documented subset parser, JavaScript and TypeScript with Codeharbor’s own tokenizer. Nothing is run.\n\nMethodology:\n- JSON: a strict RFC 8259 parser reports the first error with line and column (trailing commas, single quotes, comments and unclosed strings get their own messages) and warns about duplicate keys. Formatting keeps the key order and the exact spelling of numbers; short arrays of numbers stay on one line.\n- YAML: a subset parser (block mappings and sequences, quoted and plain scalars, one-line flow collections, block scalars, comments, several documents) reports tabs in indentation, lines indented more or less than their siblings, missing colons, mixed lists and mappings, unclosed quotes and duplicate keys. Anchors and tags are accepted but not resolved.\n- JavaScript/TypeScript: Codeharbor’s tokenizer finds unterminated strings, template literals, comments and regular expressions, unmatched or mismatched brackets, reserved words used as names and a few statement mistakes. TypeScript is first reduced to JavaScript by blanking its types (positions kept); enums, namespaces, decorators and parameter properties are reported as unsupported. This is not a full parser or a type checker.\n- CSS formatting puts one declaration per line inside indented rule blocks; HTML formatting places block elements on their own lines and indents children while keeping inline content, \u003cpre\u003e and \u003ctextarea\u003e as they are.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "codeharbor_format",
        "x-owner-app": "codeharbor",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CodeharborFormatInput"
              },
              "examples": {
                "example1": {
                  "summary": "Pretty-print minified JSON",
                  "value": {
                    "code": "{\"name\":\"harbour-api\",\"version\":\"1.4.0\",\"port\":8080,\"features\":{\"tides\":true,\"weather\":false},\"allowedOrigins\":[\"https://example.org\"]}",
                    "language": "json"
                  }
                },
                "example2": {
                  "summary": "Find the error in broken JSON",
                  "value": {
                    "code": "{\n  \"name\": \"harbour-api\",\n  \"port\": 8080,\n  \"features\": { \"tides\": true, },\n}",
                    "language": "json"
                  }
                },
                "example3": {
                  "summary": "Format minified CSS",
                  "value": {
                    "code": "body{margin:0;font:16px/1.5 system-ui}main{max-width:34rem;margin:2rem auto}button,input{padding:.5rem;border-radius:6px}",
                    "language": "css",
                    "indent": "4"
                  }
                },
                "example4": {
                  "summary": "Check YAML indentation",
                  "value": {
                    "code": "service: harbour-api\nreplicas: 2\nimage:\n  name: registry.example.org/harbour-api\n   tag: \"1.4.0\"\nenv:\n  - name: LOG_LEVEL\n    value: info\n",
                    "fileName": "deploy.yaml"
                  }
                },
                "example5": {
                  "summary": "Check a TypeScript function",
                  "value": {
                    "code": "interface Catch { boat: string; kilos: number }\nexport function total(list: Catch[]): number {\n  return list.reduce((sum, c) =\u003e sum + c.kilos, 0;\n}\n",
                    "language": "typescript"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodeharborFormatResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/codeharbor-diff/calculate": {
      "post": {
        "operationId": "calculateCodeharborDiff",
        "summary": "Compare two texts line by line and get a unified diff with added and removed lines.",
        "description": "Paste an original and a changed version of a file to see which lines were added, removed or kept, grouped into hunks with context, as a unified diff like git diff or diff -u — the same comparison Codeharbor uses for snapshots and commits.\n\nMethodology:\n- Both texts are split into lines (CRLF is treated as LF). Lines common to the start and end are set aside, then Myers’ O(ND) algorithm finds a shortest edit script between the rest: the fewest added plus removed lines.\n- Changes are grouped into hunks with the chosen number of unchanged context lines; hunks closer than twice the context are joined. The unified format shows “@@ -start,count +start,count @@” headers and lines starting with “-”, “+” or a space.\n- Similarity = 2 × unchanged lines ÷ (lines of both texts). With “ignore whitespace”, runs of spaces become one space and lines are trimmed before comparing.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "codeharbor_diff",
        "x-owner-app": "codeharbor",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CodeharborDiffInput"
              },
              "examples": {
                "example1": {
                  "summary": "Two versions of a deployment file",
                  "value": {
                    "original": "service: harbour-api\nreplicas: 2\nimage:\n  name: registry.example.org/harbour-api\n  tag: \"1.3.2\"\nresources:\n  memory: 256Mi\n",
                    "changed": "service: harbour-api\nreplicas: 3\nimage:\n  name: registry.example.org/harbour-api\n  tag: \"1.4.0\"\nresources:\n  memory: 256Mi\n  cpu: 0.5\n",
                    "originalName": "deploy.yaml (v1.3.2)",
                    "changedName": "deploy.yaml (v1.4.0)"
                  }
                },
                "example2": {
                  "summary": "Re-indented code with whitespace ignored",
                  "value": {
                    "original": "function hi() {\n  return 1;\n}\n",
                    "changed": "function hi() {\n    return 1;\n}\n",
                    "ignoreWhitespace": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodeharborDiffResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/codeharbor-markdown-preview/calculate": {
      "post": {
        "operationId": "calculateCodeharborMarkdownPreview",
        "summary": "Render Markdown to safe HTML with an outline, word count and heading checks.",
        "description": "Turns Markdown (headings, lists, task lists, tables, quotes, code blocks with highlighting, links) into sanitised HTML — raw HTML stays text — and lists the outline, word count, reading time, links and structure problems such as skipped heading levels.\n\nMethodology:\n- Block structure follows CommonMark for ATX and setext headings, paragraphs, block quotes, fenced code, thematic breaks and lists (nested by indentation); tables, task lists and ~~strikethrough~~ follow GitHub Flavored Markdown. Inline: code spans, strong, emphasis, links, autolinks and images.\n- Safety: every character of the source is HTML-escaped; raw HTML is shown as text, links are kept only for http, https, mailto and relative targets, and images point only to relative files (shown as their alt text here).\n- Headings get ids from their text (lower case, letters and digits joined by hyphens, numbered when repeated). Reading time assumes 230 words per minute. Checks: skipped heading levels, more than one level-1 heading, links to missing #anchors and images without alt text.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "codeharbor_markdown_preview",
        "x-owner-app": "codeharbor",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CodeharborMarkdownPreviewInput"
              },
              "examples": {
                "example1": {
                  "summary": "A small README",
                  "value": {
                    "markdown": "# Lighthouse Kit\n\nA **small** tool with *docs*.\n\n## Install\n\n1. Download\n2. Unpack\n3. Run `lighthouse --version`\n\n- [x] Create a project\n- [ ] Add a beacon\n\n| Key | Default |\n|---|---:|\n| port | 8080 |\n\n```js\nconst port = 8080;\n```\n\nSee [the example](#example) and \u003chttps://example.org\u003e.\n"
                  }
                },
                "example2": {
                  "summary": "Headings that skip a level",
                  "value": {
                    "markdown": "# Guide\n\n### Details\n\nText.\n\n# Second title\n\n![](diagram.png)\n"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodeharborMarkdownPreviewResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows": {
      "get": {
        "operationId": "listWorkflows",
        "summary": "Multi-tool workflows",
        "responses": {
          "200": {
            "description": "Workflow list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CodeharborFormatInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "title": "Code",
            "description": "Paste the file content.",
            "type": "string",
            "maxLength": 1000000,
            "default": ""
          },
          "language": {
            "title": "Language",
            "type": "string",
            "enum": [
              "auto",
              "json",
              "css",
              "html",
              "yaml",
              "javascript",
              "typescript",
              "markdown"
            ],
            "default": "auto"
          },
          "fileName": {
            "title": "File name (optional)",
            "description": "Used to pick the language when it is set to detect, e.g. config.yaml.",
            "type": "string",
            "maxLength": 200,
            "default": ""
          },
          "indent": {
            "title": "Indentation",
            "type": "string",
            "enum": [
              "2",
              "4"
            ],
            "default": "2"
          }
        },
        "required": []
      },
      "CodeharborFormatResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object"
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "CodeharborDiffInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "original": {
            "title": "Original",
            "type": "string",
            "maxLength": 1000000,
            "default": ""
          },
          "changed": {
            "title": "Changed",
            "type": "string",
            "maxLength": 1000000,
            "default": ""
          },
          "originalName": {
            "title": "Name of the original (optional)",
            "type": "string",
            "maxLength": 200,
            "default": "original"
          },
          "changedName": {
            "title": "Name of the changed version (optional)",
            "type": "string",
            "maxLength": 200,
            "default": "changed"
          },
          "context": {
            "title": "Context lines around changes",
            "type": "number",
            "minimum": 0,
            "maximum": 20,
            "default": 3
          },
          "ignoreWhitespace": {
            "title": "Ignore differences in spaces and indentation",
            "type": "boolean",
            "default": false
          }
        },
        "required": []
      },
      "CodeharborDiffResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object"
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "CodeharborMarkdownPreviewInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "markdown": {
            "title": "Markdown",
            "type": "string",
            "maxLength": 1000000,
            "default": ""
          }
        },
        "required": []
      },
      "CodeharborMarkdownPreviewResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object"
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}