{
  "$schema": "https://webmcp.org/schemas/model-context-v1.json",
  "name": "FlatWrite Render — Apps",
  "version": "1.0.0",
  "surfaceMode": "app",
  "status": "ready",
  "handlers": [
    {
      "url": "https://render.flatwrite.md/render?surface=app",
      "transport": "http",
      "method": "POST",
      "headers": {
        "Content-Type": "application/json"
      },
      "authNote": "Browser clients mint a short-lived X-Mcp-Token from https://render.flatwrite.md/mcp-token first. Server-to-server clients may use X-Api-Key directly."
    }
  ],
  "tools": [
    {
      "name": "render_markdown",
      "description": "Render markdown into FlatWrite-styled HTML <head> and <body> fragments for the app surface. Provide either the raw markdown inline (`markdown`) or an allowlisted URL (`markdownUrl`). Use this when you need the rendered HTML artifacts for the app surface.",
      "category": "render",
      "inputSchema": {
        "type": "object",
        "properties": {
          "markdown": {
            "type": "string",
            "description": "Raw markdown content to render."
          },
          "markdownUrl": {
            "type": "string",
            "description": "URL pointing to raw markdown content. Must be on an allowlisted host (raw.githubusercontent.com, raw.gitlab.com, bitbucket.org), http(s) only, and <=1 MB. Host validation is enforced server-side."
          },
          "font": {
            "type": "string",
            "description": "Font family — must be a bundled family.",
            "enum": [
              "Inter",
              "JetBrains Mono",
              "Lato",
              "Lora",
              "Merriweather",
              "Playfair Display",
              "Comfortaa",
              "Unbounded"
            ]
          },
          "appFramework": {
            "type": "string",
            "description": "UI framework applied when surfaceMode=\"app\".",
            "enum": [
              "spectre",
              "poshui",
              "pico",
              "milligram",
              "chota"
            ]
          },
          "size": {
            "oneOf": [
              {
                "type": "string",
                "description": "Scale token (e.g. \"-1\", \"0\", \"1\")"
              },
              {
                "type": "number",
                "description": "Absolute pixel value (8..72)"
              }
            ],
            "description": "Font size as a scale token (e.g. \"-1\", \"0\", \"1\").",
            "minimum": 8,
            "maximum": 72
          },
          "weight": {
            "oneOf": [
              {
                "type": "string",
                "description": "Scale token (e.g. \"-1\", \"0\")"
              },
              {
                "type": "number",
                "description": "Absolute weight (100..900, multiples of 100)"
              }
            ],
            "description": "Font weight as a scale token (e.g. \"-1\", \"0\").",
            "minimum": 100,
            "maximum": 900
          },
          "line": {
            "oneOf": [
              {
                "type": "string",
                "description": "Scale token (e.g. \"-1\", \"0\", \"1\")"
              },
              {
                "type": "number",
                "description": "Absolute multiplier (0.8..4.0)"
              }
            ],
            "description": "Line height as a scale token (e.g. \"-1\", \"0\", \"1\").",
            "minimum": 0.8,
            "maximum": 4
          },
          "uiZoom": {
            "type": "number",
            "description": "UI zoom level (1.0 = default; >1 zooms in, <1 zooms out).",
            "minimum": 0.25,
            "maximum": 4
          },
          "pageSize": {
            "type": "string",
            "description": "Page size for paged output. Only effective when docEngine is pagedjs or vivliostyle.",
            "enum": [
              "A0",
              "A1",
              "A2",
              "A3",
              "A4",
              "A5",
              "Letter",
              "Legal"
            ]
          },
          "orientation": {
            "type": "string",
            "description": "Page orientation.",
            "enum": [
              "portrait",
              "landscape"
            ]
          },
          "marginsLR": {
            "type": "string",
            "description": "Left/right page margin preset. Only effective when docEngine is pagedjs or vivliostyle.",
            "enum": [
              "narrow",
              "normal",
              "wide"
            ]
          },
          "marginsTB": {
            "type": "string",
            "description": "Top/bottom page margin preset. Only effective when docEngine is pagedjs or vivliostyle.",
            "enum": [
              "narrow",
              "normal",
              "wide"
            ]
          },
          "footer": {
            "type": "boolean",
            "description": "Include a page-number footer in paged output."
          },
          "width": {
            "type": "number",
            "description": "Content width in pixels (400..1400). Only effective when docEngine=\"none\".",
            "minimum": 400,
            "maximum": 1400
          },
          "docEngine": {
            "type": "string",
            "description": "Document engine — \"none\" emits plain CSS; \"pagedjs\"/\"vivliostyle\" wrap the output in @page rules.",
            "enum": [
              "none",
              "pagedjs",
              "vivliostyle"
            ]
          },
          "surfaceMode": {
            "type": "string",
            "description": "Surface mode hint. \"app\" unlocks the appFramework picker; otherwise this is metadata only.",
            "enum": [
              "doc",
              "app"
            ]
          },
          "theme": {
            "type": "string",
            "description": "Theme identifier rendered as body[data-theme=\"...\"] so consumer CSS can theme via attribute selectors. Free-form (alphanumeric, dash, underscore) — common values are \"light\" and \"dark\"."
          }
        },
        "required": [],
        "oneOf": [
          {
            "required": [
              "markdown"
            ]
          },
          {
            "required": [
              "markdownUrl"
            ]
          }
        ]
      },
      "outputSchema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "True on successful render."
          },
          "kind": {
            "type": "string",
            "enum": [
              "html"
            ],
            "description": "Output format — always \"html\" for render tools."
          },
          "document": {
            "type": "object",
            "properties": {
              "title": {
                "description": "Best-effort title extracted from the first H1 heading.",
                "type": "string"
              },
              "wordCount": {
                "description": "Approximate word count of source markdown.",
                "type": "number"
              },
              "charCount": {
                "description": "Character count of source markdown.",
                "type": "number"
              }
            },
            "additionalProperties": false
          },
          "artifacts": {
            "type": "object",
            "properties": {
              "head": {
                "type": "string",
                "description": "Self-contained <head> fragment."
              },
              "body": {
                "type": "string",
                "description": "Self-contained <body> fragment."
              }
            },
            "required": [
              "head",
              "body"
            ],
            "additionalProperties": false
          },
          "warnings": {
            "description": "Non-fatal warnings.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "ok",
          "kind",
          "artifacts"
        ],
        "additionalProperties": false,
        "description": "Rendered markdown as self-contained HTML fragments with document metadata."
      },
      "annotations": {
        "readOnlyHint": true
      },
      "displayHints": {
        "inputFieldAliases": {
          "font": "fontFamily",
          "appFramework": "framework",
          "size": "fontSize",
          "weight": "fontWeight",
          "line": "lineHeight"
        }
      }
    },
    {
      "name": "list_render_options",
      "description": "Return the supported fonts, UI frameworks, document engines, page sizes, orientations, margins, and surface modes for the render_markdown tool. Call this before rendering if you need to know which enum values are valid.",
      "category": "discovery",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "required": []
      },
      "outputSchema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "Always true for successful options listing."
          },
          "options": {
            "type": "object",
            "properties": {
              "fonts": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Bundled font families that can be passed as fontFamily."
              },
              "frameworks": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "UI frameworks that can be passed as framework when surfaceMode is \"app\"."
              },
              "docEngines": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Document engines that can be passed as docEngine."
              },
              "pageSizes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Page size presets that can be passed as pageSize."
              },
              "orientations": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Page orientations that can be passed as orientation."
              },
              "margins": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Page margin presets that can be passed as marginsLR or marginsTB."
              },
              "surfaceModes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Surface mode hints that can be passed as surfaceMode."
              }
            },
            "required": [
              "fonts",
              "frameworks",
              "docEngines",
              "pageSizes",
              "orientations",
              "margins",
              "surfaceModes"
            ],
            "additionalProperties": false,
            "description": "Supported enum values for each render option category."
          },
          "defaults": {
            "description": "Default values used when an option is omitted.",
            "type": "object",
            "properties": {
              "font": {
                "description": "Default font family.",
                "type": "string"
              },
              "docEngine": {
                "description": "Default document engine.",
                "type": "string"
              },
              "surfaceMode": {
                "description": "Default surface mode.",
                "type": "string"
              },
              "pageSize": {
                "description": "Default page size.",
                "type": "string"
              },
              "orientation": {
                "description": "Default orientation.",
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "ok",
          "options"
        ],
        "additionalProperties": false,
        "description": "Supported values for the render_markdown tool, wrapped in a typed envelope."
      },
      "annotations": {
        "readOnlyHint": true
      },
      "displayHints": {
        "inputFieldAliases": {}
      }
    }
  ]
}
