Skip to main content
Glama
Kydaix

Font Design MCP

by Kydaix

Font Design MCP

Draw, inspect, refine, and build fonts through MCP.

A local MCP server for AI-assisted type design, from vector outlines to TTF and WOFF2.

CI Python: 3.11–3.13 License: MIT

English · Français

Get started · Connect a client · Report an issue


Get started

Version 0.6.0 adds regional stroke checks, interpolation diagnostics, persistent stroke constructions, and revision-bound visual release evidence. See the release notes and quality and release guide. Installation runs directly from GitHub, with automatic client detection. With Node.js 20+ and Git, run:

npx --yes github:Kydaix/Font-Design-MCP

The installer prepares uv and Python 3.13 if needed, installs the MCP in a persistent environment, detects Codex, Claude Code and Cursor, and asks which clients to configure. Restart those clients after installation. MCP tools belong to the client application and are available to its compatible models.

npx --yes github:Kydaix/Font-Design-MCP --clients codex cursor
npx --yes github:Kydaix/Font-Design-MCP --yes
npx --yes github:Kydaix/Font-Design-MCP --clients codex --dry-run

--yes selects all detected clients; --clients explicitly selects one or more, including claude-code. --workspace /absolute/path chooses where fonts are saved. --dry-run prepares the runtime but only previews client changes. Existing configuration files receive a .font-design-<id>.bak backup before atomic replacement. Other servers and existing per-server settings are preserved. Invalid configuration files are refused. Re-running the command updates the installation without duplicating server entries. An existing workspace is retained unless --workspace or FONT_DESIGN_MCP_WORKSPACE explicitly changes it.

Each install creates a separate runtime, so active servers do not block Windows updates. Previous runtimes are retained for running clients and configuration backups. The installed runtime survives removal of the npm cache. Remove its MCP entry in a client to disconnect it; font projects remain in the workspace. The MCP is distributed through GitHub, without publishing to PyPI or npm. Python dependencies still download from their package index on first installation. Pin a checkout with github:Kydaix/Font-Design-MCP#v0.6.0.

For manual setup, font-design-mcp config prints JSON using the versioned GitHub release wheel; config --from /absolute/path/package.whl uses a downloaded wheel. Neither command edits client files.

--workspace overrides FONT_DESIGN_MCP_WORKSPACE, which overrides the dedicated user-data default: %LOCALAPPDATA%/font-design-mcp/workspace on Windows, ~/Library/Application Support/font-design-mcp/workspace on macOS, $XDG_DATA_HOME/font-design-mcp/workspace (or ~/.local/share/...) on Linux. The workspace stays outside UV's cache and survives upgrades or extension removal.

The MCPB extension targets hosts supporting the UV runtime in manifest 0.4.

Development from source

  1. Clone the repository and install the dependencies with the commands below.

  2. Run the diagnostic and demo to generate your first font specimen.

  3. Connect your MCP client to start designing with an agent.

Requirements: Python 3.11–3.13, uv, and a GitHub account with access to this repository. Commands work in PowerShell and POSIX shells.

git clone https://github.com/Kydaix/font-design-mcp.git
cd font-design-mcp
uv sync --frozen --python 3.11
uv run --frozen font-design-mcp doctor
uv run --frozen python examples/demo.py --workspace ./workspace

doctor checks dependencies and rasterizes a PNG; doctor --build also compiles TTF and WOFF2. Font operations run locally after installation; the server needs no model API key or proprietary editor. The client agent may use a remote model.

The demo launches a real STDIO server through the official MCP Python SDK. It draws A, V, O, Q, acute, and Á, sets AV kerning to −80 units, moves A's apex, compares revisions, validates, and builds both export formats. Each run creates a new project and prints the path to specimen.html. Open it directly in a browser.

Demo output

Contents

specimen.html

Read-only previews and links to the generated fonts; no web server needed

demo-calls.json

The MCP calls and their structured results

demo-report.json

Project, revision, source, build, and validation references

revisions/ and artifacts/

UFO snapshots, PNGs, TTF/WOFF2, parameters, and hashes

Generated workspaces stay local and are ignored by Git.

Related MCP server: FontLab MCP Server

Miette: a rounded typeface example

Miette Regular is an original, soft rounded font with 84 letters: uppercase and lowercase Latin, French accents, and æ/œ/Æ/Œ. Basic punctuation and spaces bring the total to 107 encoded characters. Its drawings, accent components, optical kerning, and complete MCP build recipe are included.

Miette, an original rounded typeface created with Font Design MCP

Download TTF · Download WOFF2 · Specimen and reproduction

Open examples/miette/specimen.html locally to type your own text, adjust its size, and compare kerning. This first Regular style focuses on French letters; digits and additional styles are not included.

Connect a client

The MCP client launches the server process. Set an absolute interpreter path and an absolute workspace path in the client's configuration:

{
  "mcpServers": {
    "font-design": {
      "command": "/absolute/path/font-design-mcp/.venv/bin/python",
      "args": ["-m", "font_design_mcp", "serve", "--workspace", "/absolute/path/font-workspace"]
    }
  }
}

On Windows, use C:/path/font-design-mcp/.venv/Scripts/python.exe for command and a Windows absolute path for the workspace. The user sets this directory at launch; a tool call cannot expand it.

Add a block like this to your Codex configuration, adapting both paths:

[mcp_servers.font_design]
command = "/absolute/path/font-design-mcp/.venv/bin/python"
args = ["-m", "font_design_mcp", "serve", "--workspace", "/absolute/path/font-workspace"]
startup_timeout_sec = 20
tool_timeout_sec = 180

The format follows the official Codex MCP documentation. The Windows example needs its installation-specific paths adjusted. The SDK client is tested end to end. Miette also exercised a live Codex MCP connection on Windows, including project creation, inspection, image previews, and font exports.

Windows / PowerShell:

.\.venv\Scripts\font-design-mcp.exe serve --workspace "$PWD\workspace"

macOS / Linux:

.venv/bin/font-design-mcp serve --workspace "$PWD/workspace"

The process waits for MCP messages on stdin. Stdout is reserved for JSON-RPC, so there is no startup banner. Logs go to stderr or captured compiler logs. Using the installed executable avoids dependency resolution at server startup. Normally, let the client start the process itself.

Image visibility depends on the client. Render tools return actual MCP image blocks, plus persistent paths, dimensions, hashes, and revisions. The client must forward those images to a model that can use them.

Design a font

The client agent makes the creative decisions; the server applies validated operations and keeps a revision history.

Step

What you can do

Draw

Start with a brief and a few structural glyphs. Create lines, cubic and quadratic curves, counters, components, and anchors.

Preview and refine

Inspect PNG previews with guides and handles. Move points by stable ID and compare revisions at the same sizes.

Space and kern

Stabilize proportions, set side bearings, then adjust kerning. Test words with kerning on and off before extending the alphabet.

Validate and export

Check geometry, coverage, and compilation. Build TTF and WOFF2 from a frozen revision.

Record hypotheses and observed corrections in the project's decision journal.

The development version adds default outline diagnostics, perpendicular stroke/counter profiles and revision-bound visual reviews. font_build defaults to a proof export; purpose="release" requires an explicit review contract. See the quality and release workflow.

Every call names its project. Source edits require expected_revision; stale requests fail instead of overwriting another edit. Points and handles have stable IDs, so a correction can be as small as:

{
  "op": "move_point",
  "point_id": "Aouter_1",
  "x": 340,
  "y": 720
}

Pass this operation in glyph_edit.operations with the project ID, glyph ID, and current expected revision. A successful edit returns the new revision and changed IDs. compare_revision on either render tool shows two revisions under the same viewing conditions.

Technical validation and the agent's judgement are distinct from human approval. The server does not assign an artistic score or accept an agent-supplied claim of authenticated human approval.

Work from your own drawings

Import explicitly calibrated PNG references with reference_import, preserve their distinctive features, and compare reconstructed outlines with render_glyph(reference_id=...). Use design_spec to retain coverage and measurable style targets, font_analyze to find localized issues, and render_proof to compare letters and digits at a common scale. Handle-preserving edits and optionally linked accents prevent some local corrections from breaking related geometry.

This is controlled reconstruction and review, not automatic tracing or a guarantee of professional quality. See the reference-driven design workflow for calibration, examples, limits, optional export checks and schema-3 compatibility.

Available tools

The official MCP SDK publishes input and output schemas through tools/list. Responses include structured data, readable summaries, revisions, warnings, and identifiable errors.

Tool

Purpose

project_create

Create a project with metadata, metrics, and an optional brief

project_open

Reopen a server-created project and verify its integrity

project_inspect

Read metadata, metrics, kerning, and a paginated glyph inventory

project_update

Update the brief, supported metadata, vertical metrics, or decision journal

glyph_get

Inspect contours, IDs, components, anchors, advance, bounds, and bearings

glyph_edit

Apply a typed, atomic vector-editing batch to a glyph

font_edit

Edit up to 128 glyphs and their spacing atomically in one revision

spacing_edit

Set advances, side bearings, kerning pairs, and kerning groups

render_glyph

Render a glyph with optional guides, handles, and revision comparison

render_text

Compile, shape, and render text at multiple sizes

reference_import

Import a calibrated PNG from workspace/inbox as an immutable drawing reference

font_analyze

Check visible ink, matching outlines, crossings, design coverage and declared metrics/profiles

proof_review

Record an agent assessment of immutable proofs and intentional localized findings

font_release_check

Report missing measurements, glyph/text reviews and unresolved findings across masters

render_proof

Compare multiple glyphs at a shared scale, optionally across revisions

font_validate

Check geometry, Unicode coverage, compilation, and OpenType tables

font_build

Export static or variable TTF and/or WOFF2 from a frozen revision

variable_configure

Define continuous axes and clone/edit the project's master configuration

history_list

Browse committed revisions and change summaries

history_restore

Restore an earlier state by creating a new revision

Exact input and output schemas are available through MCP tools/list.

Inspection, glyph reads/edits, batch edits, validation, and renders default to detail="summary". Use detail="full" for complete data, including point IDs before editing them; render_text also accepts detail="positions". Rendered images remain inline by default; image_mode="resource" returns references for retrieval through MCP resources.

Save and restore your work

UFO 3 is authoritative for outlines. Design contracts and links are revisioned in the manifest. Compiled fonts and preview images are derived artifacts; imported drawing references are project inputs and their referenced artifacts/ entries must be retained and backed up with the project:

workspace/<project_id>/
├── HEAD.json
├── revisions/<revision>/
│   ├── source.ufo/
│   └── manifest.json
└── artifacts/<artifact_id>/
    ├── font.ttf / font.woff2 / image.png
    └── artifact.json

Edits validate the whole project, write a complete new UFO snapshot, then atomically update the revision pointer under an OS lock. Invalid batches leave the committed state intact. Hashes detect external changes; restoration preserves existing history. Back up the entire project directory, preferably with the server stopped.

Use a private local workspace and edit snapshots through the tools. The server checks paths and UFO references, rejects symlinks/junctions and unsafe XML, and exposes no arbitrary code, shell, download, or package-installation tool. Inputs, images, geometry, compiler time, and logs are bounded. These checks are not an OS sandbox against a hostile process with the same user privileges, and snapshots are not a substitute for an external backup. Disk usage has no automatic global quota or history purge.

Coordinates use font units, baseline y=0, with Y pointing up. Advance, visible width, and side bearings are different measurements. UPM is fixed at creation. Closed contours use non-zero filling; counters need the opposite winding.

Supported formats and limits

Current scope: static and variable TTF/WOFF2 fonts, freeform closed contours, components, anchors, and kerning. Text is shaped with HarfBuzz from a compiled TTF and rasterized with FreeType/Pillow, without system-font fallback.

For variable fonts, variable_configure defines axes and clones masters within the same project. Editing tools accept master_id, render_text accepts location: {"wght": 500}, and font_build automatically exports a variable font. Up to 4 continuous axes and 8 masters, subject to source size limits.

Not supported in this version: OTF, arbitrary UFO/SVG import, image tracing, editor adapters, collaborative networking, and a full graphical editor. No hinting or arbitrary OpenType feature code is exposed. Text previews are single-line specimens, not paragraph layout.

Precomposed Á built from components is tested. Latin combining marks with matching base/mark anchors are checked for reachable mark positioning in TTF and WOFF2, including variable exports and cached builds. Stacked marks (mkmk) and complex-script coverage are not certified. Source previews can differ slightly from compiled contours after curve conversion, and unhinted FreeType output need not match native OS rendering.

Build from source

After completing Get started, build the source archive and wheel:

uv build

Output: dist/. Dependency versions are pinned in pyproject.toml and uv.lock; requirements.lock provides hashed dependencies for pip installations. Install them with pip install --require-hashes -r requirements.lock, then install the built wheel with pip install --no-deps /path/to/package.whl.

Checks

uv run --frozen pytest -q
uv run --frozen ruff check src tests scripts examples
uv run --frozen python tests/test_acceptance.py

The standalone acceptance client retains its captures and JSON-RPC transcript under test-output/acceptance-*. It checks actual compiled kerning, edit isolation, revision conflicts, failed atomic batches, unsafe paths, compiler failure, restart, and interrupted writes.

Verification

Evidence

Windows 11 x64, Python 3.11

53 local tests passed, including client installation, variable interpolation, real STDIO calls, atomic edits, rendering, and recovery

Windows, macOS, Linux runners

CI results, covering Python 3.11 and 3.13

Installed wheel

Entry point and full MCP demo tested in a separate environment

MCPB extension

Installed outside the repository; diagnostic, STDIO calls, and TTF/WOFF2 exports tested

The CI result covers its runner environments, not every OS version or CPU architecture.

Credits and license

Built with the official MCP Python SDK, UFO sources, HarfBuzz, and FreeType/Pillow. Third-party notices are included in the installed dependency packages.

The server code and original examples are MIT licensed. This does not automatically license fonts you create with the server. Font license metadata is empty by default and remains under the creator's control. No third-party font outlines or font files are included.

Available Tools

20 tools
font_analyzeC

Check visible ink, matching outlines and self crossings by default; measure declared design rules, normal stroke/counter profiles, smooth joins, digit spacing and required coverage. Rules accept master_id or a variable location; variation_profiles measure normal-width progression. interpolation=true adds timed source correspondence and compiled axis-grid checks. Returns regional coverage and localized candidates, not artistic approval. Full reports include measurements and evidence_plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
detailNosummary
revisionNo
master_idNodefault
project_idYes
interpolationNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

C2.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=false) already convey the safety/idempotency profile. The description adds useful behavioral context the annotations lack: what is checked by default, what interpolation adds, and that the output is 'regional coverage and localized candidates, not artistic approval' with 'measurements and evidence_plan'. It does not explain why the operation is non-read-only/non-idempotent (likely report generation), leaving a gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is compact and avoids padding, and the default checks are front-loaded. But the semicolon-packed, jargon-heavy prose is hard to parse and buries the top-level purpose, so the structure does not maximize clarity per token.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be re-explained, and the description covers several behavioral/parameter facets. Still, with 5 parameters at 0% schema coverage, no usage routing among siblings, and no explanation of the non-read-only nature, it is only adequately complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load: it adds meaning for master_id ('Rules accept master_id or a variable location') and for interpolation ('adds timed source correspondence and compiled axis-grid checks'), and indirectly for detail ('Full reports include...'). It says nothing about revision or project_id, so compensation is only partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names concrete check categories ('visible ink', 'matching outlines', 'self crossings', 'digit spacing') and implies an analysis/QA role over a font project, so the general purpose is inferable. However it never states plainly what resource is being analyzed or how it differs from siblings like font_validate or font_release_check, and the dense jargon obscures the core purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance, and no alternative tool is named. The only conditional language ('by default', 'interpolation=true adds...') describes parameter behavior rather than the choice between this tool and its siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

font_buildB

Build real TTF and/or WOFF2 from a frozen revision, automatically variable when axes/masters are configured. Returns persistent relative paths and hashes. Does not alter sources.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatsNo
purposeNoproof
revisionNo
project_idYes
review_urisNo
require_design_checksNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false, so the mutation profile is known. The description adds useful context ('Does not alter sources', 'Returns persistent relative paths and hashes', automatic variable output), but omits whether builds are cached, whether they overwrite existing artifacts, or any auth/permission requirements. Given annotations cover the safety profile, this additional context earns a middle score.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences with no filler, front-loading the core action and then the behavioral guarantees. Every clause supplies information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is unnecessary. However, for a 6-parameter, mutation-performing build tool with 0% schema description coverage, the absence of parameter-level guidance (especially purpose and the check/review options) leaves the agent under-informed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the burden for 6 parameters. It mentions formats implicitly ('TTF and/or WOFF2') and the revision source ('from a frozen revision'), but does not explain purpose (proof vs release), require_design_checks, review_uris, or project_id. It leaves most parameters undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: building real TTF/WOFF2 from a frozen revision, and notes automatic variable output when axes/masters are configured. Does not explicitly distinguish itself from font_release_check or font_validate siblings, but the build output (font binaries) is clearly distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance. There is no mention of alternatives such as font_release_check or font_validate, nor any indication of when a 'proof' vs 'release' build should be performed despite that distinction existing in the schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

font_editB

Edit up to 128 glyphs atomically in master_id (default: 'default'), then apply spacing. Forward component references resolve at final validation; any failure rolls back the batch.

ParametersJSON Schema
NameRequiredDescriptionDefault
detailNosummary
glyphsYes
spacingNo
summaryNo
master_idNodefault
project_idYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnly=false, idempotent=false, destructive=false), and the description adds real behavior beyond them: atomicity, rollback on any failure, and deferred resolution of forward component references at final validation. That last point materially affects how a caller sequences dependent operations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences, front-loaded with the action and scope, then the correctness guarantees. No filler and no repetition of structured data beyond the master_id default.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with a very large nested schema and no output-value burden (an output schema exists), the description is too thin: it omits expected_revision semantics, the create flag on GlyphChange, and any sense of what the glyphs/spacing operation payloads do. Adequate for safety, inadequate for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 7 parameters, and the description explains only master_id (including its default). The heavyweight inputs the agent must construct – glyphs with its 19-way operation union, spacing, project_id, expected_revision, summary, detail – are left entirely to the schema, and expected_revision's optimistic-concurrency role is never stated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (edit), resource (glyphs), and scope (up to 128, atomically in master_id, plus spacing). This distinguishes it from glyph_edit and spacing_edit implicitly via the batch/atomic/covers-both framing, but it never names a sibling to route the agent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use statement. The atomic 128-glyph batch with a trailing spacing pass implies the use case is bulk edits, but an agent must infer this and has no guidance on choosing between font_edit, glyph_edit, and spacing_edit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

font_release_checkB

Evaluate all masters, structural measurements, glyph review coverage, localized findings, reference comparisons and shaped text reviews before release. Supply proof_review report_uris. Returns actionable missing requirements; never certifies aesthetic perfection.

ParametersJSON Schema
NameRequiredDescriptionDefault
revisionNo
project_idYes
review_urisNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false, destructiveHint=false, idempotentHint=false and a closed world, so the agent already knows this is a non-destructive but non-idempotent state-affecting call. The description adds that it returns actionable missing requirements and 'never certifies aesthetic perfection', which usefully sets expectations, but it does not disclose what side effects the check has or what it persists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences, with the scope of the evaluation front-loaded before the input instruction and the return-value caveat. The long enumeration of check categories is dense but each item is informative and nothing is repeated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return format need not be documented, and the description does note the actionable-findings nature of the result. However, for a state-affecting tool with 0% parameter documentation, the description leaves the meaning of project_id/revision and the overall side-effect profile underspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 3 parameters, so the description carries the full burden, yet it only hints at one of them ('supply proof_review report_uris' loosely maps to review_uris). project_id and revision receive no explanation, and the accepted URI format/limit is left entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (Evaluate) and enumerates the concrete resource scope: masters, structural measurements, glyph review coverage, localized findings, reference comparisons, shaped text reviews, before release. That is far more specific than a tautology and separable from siblings like font_validate or font_analyze, though it never explicitly contrasts itself with them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'before release' implies timing and the instruction to 'Supply proof_review report_uris' hints at a prerequisite, but no sibling is named as an alternative and no exclusion is stated (e.g., when to use font_validate instead). Usage is implied rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

font_validateB

Run technical checks, compile a TTF, inspect tables and corpus coverage. Reports errors, warnings and observations; does not assess artistic merit.

ParametersJSON Schema
NameRequiredDescriptionDefault
corpusNo
detailNosummary
revisionNo
project_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are minimal (all hints false), so the description carries the behavioral burden. It discloses that it compiles a TTF, inspects tables, and reports errors/warnings/observations. However, it does not clarify whether the compiled TTF is persisted, whether any project state is modified, or what side effects occur. The 'compile' action implies potential file creation, but the description is vague about persistence. It also doesn't mention permissions or reversibility. This is partial transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no wasted words. It front-loads the primary actions (run checks, compile, inspect) and adds the reporting scope and the artistic merit exclusion. Every clause earns its place. It is compact and readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 4 parameters, an output schema, and complex behavior (compilation, inspection). The description is far too sparse to be complete. It does not explain parameter usage, when to use it versus font_build, or what the output report includes beyond errors/warnings/observations. Even though an output schema exists, the description should still clarify the tool's role and parameter semantics. The missing guidance leaves significant gaps for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description provides essentially no parameter-level semantics. It mentions 'corpus coverage' which alludes to the corpus parameter but does not explain it, nor does it explain detail (summary vs full), revision, or the purpose of project_id beyond the obvious. With zero coverage, the description must compensate by explaining each parameter, and it fails to do so. The agent is left to guess what these parameters control.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Run technical checks', the resource (a font/project via project_id), and specific actions: compile a TTF, inspect tables and corpus coverage. It also explicitly differentiates by stating it does not assess artistic merit, which distinguishes it from render or edit tools. The purpose is unambiguous and well-scoped.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives. It mentions 'technical checks' but does not name sibling tools like font_build or render_glyph, nor does it state conditions for choosing this over them. The 'does not assess artistic merit' hint is too implicit to serve as a routing rule. An agent would have to infer when to invoke this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

glyph_editC

Apply typed vector operations or drawing primitives atomically to one glyph in master_id (default: 'default'). Use detail=full for added/removed/touched IDs. Replacements are explicit.

ParametersJSON Schema
NameRequiredDescriptionDefault
createNo
detailNosummary
summaryNo
glyph_idYes
master_idNodefault
operationsYes
project_idYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the safety bar is lower. The description usefully adds that operations are applied 'atomically' and that 'replacements are explicit', which is real behavioral context beyond the annotations, but it omits the concurrency semantics (expected_revision) that govern a mutation of this kind.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly written sentences with the primary action front-loaded and no filler. It is efficient, though 'Replacements are explicit' is somewhat cryptic in isolation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a highly complex mutation tool (19 operation variants, 8 params, optimistic concurrency via expected_revision, and a create flag), the description is far too terse. An output schema exists so return values need not be explained, but the missing param coverage and lack of concurrency/creation guidance leave real gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the full explanatory burden, yet it only mentions master_id's default and the detail=full option. Key parameters such as expected_revision, create, and the 19-variant operations payload receive no explanation, leaving the parameter semantics largely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (apply) and resource (typed vector operations/drawing primitives to one glyph in a master), which is clear. It does not, however, differentiate itself from siblings like glyph_get or font_edit, so an agent must infer the boundary from the word 'operations' alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus font_edit, glyph_get, or spacing_edit. The only conditional offered is the detail=full hint, which concerns output verbosity, not tool selection. No prerequisites or exclusions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

glyph_getA
Read-onlyIdempotent

Read a master's glyph metrics in font units, Y upwards. master_id defaults to 'default'. Use detail=full for contour/point/component/anchor IDs and geometry.

ParametersJSON Schema
NameRequiredDescriptionDefault
detailNosummary
glyph_idYes
revisionNo
master_idNodefault
project_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds valuable behavioral context beyond annotations by specifying the coordinate system (Y upwards) and what detail=full reveals (contour/point/component/anchor IDs and geometry). It does not cover pagination or errors, but these are less critical for a simple read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no fluff. The primary action is front-loaded, and the detail=full guidance is placed second. Every word serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists (has output schema: true), the description need not detail return values. It covers the essential purpose, coordinate system, and the main optional parameter behavior. It doesn't mention revision handling or edge cases, but these are secondary for a read-only tool with strong annotations and schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds meaning for 'detail' by explaining what detail=full returns and notes that master_id defaults to 'default' (already in schema). However, it does not explain 'revision', 'project_id', or 'glyph_id', which are not self-evident. The partial compensation warrants a 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('Read a master's glyph metrics'), the resource (master's glyph), and adds relevant details (font units, Y upwards). It distinguishes itself from siblings like glyph_edit (write) and render_glyph (rendering) by focusing on reading metrics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives guidance on parameter usage ('Use detail=full for contour/point/component/anchor IDs and geometry') but does not explicitly address when to use this tool versus alternatives. It lacks 'when not to use' or references to sibling tools like glyph_edit or render_glyph, so an agent must infer the appropriate context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_listB
Read-onlyIdempotent

List committed revisions and summaries with pagination; interrupted uncommitted stages are excluded.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
detailNosummary
offsetNo
revisionNo
project_idYes
include_totalNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds a meaningful behavioral detail: it excludes interrupted uncommitted stages, which is not inferable from annotations and helps the agent understand the tool's scope.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that conveys purpose and a key exclusion without waste. It is appropriately concise for the tool's straightforward nature.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 6 parameters and 0% schema description coverage, the description is incomplete. It fails to explain parameter semantics, and while an output schema exists, the tool's behavior regarding filtering by revision or detail level is undocumented. The description is too sparse to fully guide correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for parameter meanings. It mentions pagination but does not explain limit, offset, detail, revision, include_total, or how they interact. The schema itself provides defaults and constraints but no descriptions, leaving the agent without guidance on parameter usage beyond names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists committed revisions and summaries, with a specific exclusion of interrupted uncommitted stages. It uses a specific verb ('List') and resource, but does not explicitly differentiate from sibling tools like history_restore, though the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for listing committed revisions only, and notes that uncommitted stages are excluded, which hints at when not to use it. However, it does not mention alternative tools or explicit when-to-use conditions, leaving some inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_restoreA

Restore a committed revision by creating a NEW revision; requires the current expected_revision and preserves history.

ParametersJSON Schema
NameRequiredDescriptionDefault
summaryNo
project_idYes
target_revisionYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a non-read-only, non-idempotent, and non-destructive operation. The description adds valuable context by clarifying it creates a NEW revision (so no overwrite) and preserves history, reinforcing the non-destructive nature. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, compact sentence front-loads the core action and key precondition. Every clause adds meaningful information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the purpose, the non-destructive behavior, and the main precondition. With an output schema present, return details are not required. However, it omits explicit guidance on error conditions or concurrency failure handling, which could be helpful for a mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explicitly explains expected_revision ('current expected_revision') and implies target_revision (the revision to restore), but it does not clarify project_id or summary. This partially bridges the schema gap but leaves two parameters under-explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Restore a committed revision') and the mechanism ('by creating a NEW revision'), distinguishing it from history_list (which lists revisions) and project_update (which modifies settings). It also highlights a critical requirement (expected_revision) that sets it apart from simple reads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage context by requiring the current expected_revision, suggesting a concurrency-aware restore. However, it does not explicitly contrast with sibling tools or state when NOT to use it, leaving some inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

project_createC

Create a project in the launch workspace with Unicode UFO sources and technical glyphs.

ParametersJSON Schema
NameRequiredDescriptionDefault
briefNo
metricsNo
metadataYes
design_specNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, and openWorldHint=false, so the safety profile is covered. The description adds essentially no behavioral context beyond those annotations — no side effects, permissions, or post-creation state are described.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The single sentence is front-loaded with the verb and contains no filler. It is concise, though arguably too terse for the complexity of the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a required nested metadata object and a sprawling design_spec with many sub-definitions, the description is far too thin. The output schema exists so returns need not be explained, but the description does not help an agent populate the rich input structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Top-level schema description coverage is 0%, so the description must carry parameter meaning, but it only loosely gestures at 'UFO sources and technical glyphs.' It does not explain 'brief,' 'metrics,' 'metadata,' or the very complex 'design_spec,' leaving the agent to reverse-engineer the nested schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Create') and resource ('project') and adds scope ('in the launch workspace') plus content hints ('Unicode UFO sources and technical glyphs'). It is distinguishable from project_open and project_update by the verb, but it does not explicitly differentiate itself from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives, no prerequisites, and no mention of when not to use it. The sentence describes the outcome but gives an agent no decision context beyond the bare verb.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

project_inspectB
Read-onlyIdempotent

Inspect a master with optional sections and glyph_ids focus. Full collections are paginated; pagination lists each continuation. Use sections=['design'] for the complete design contract without spacing/compositions.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
detailNosummary
offsetNo
revisionNo
sectionsNo
glyph_idsNo
master_idNodefault
project_idYes
include_totalNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety bar is low. The description adds genuinely new behavioral context beyond the annotations: full collections are paginated and each continuation is listed, and the design section's scope is qualified. Return format is not described, hence not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action, and no filler. It could be marginally tighter but every sentence carries content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and pagination is disclosed. However, for a 9-parameter tool with zero schema coverage and an enum-driven detail mode, the description leaves too many parameters and the summary-vs-full behavior unaddressed to be considered complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 9 parameters, so the description must carry the load. It only addresses two of them (sections, glyph_ids) and leaves limit, offset, detail, revision, master_id, and include_total entirely unexplained, including which value of detail the pagination note applies to.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb (Inspect) and resource (a master), plus the scoping axes (sections, glyph_ids). An agent can distinguish it from project_open/project_create, but the description never says it is a font-master inspection or names a sibling to differentiate against, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

One explicit usage hint is given: sections=['design'] yields the complete design contract without spacing/compositions. That is real guidance for one path, but there is no when-to-use-this-vs-project_open, no exclusion conditions, and no guidance on detail/offset/limit selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

project_openA
Read-onlyIdempotent

Reopen a server-created project by ID; verifies committed sources and returns its revision.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering safety traits. The description adds extra behavior: that it verifies committed sources and returns a revision, which is not in the annotations and gives useful operational context. This enriches transparency without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, compact sentence that states the action, target, and key outcomes. It is front-loaded with the verb and resource, and every phrase adds value. No filler or redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only operation with one parameter and an output schema present, the description covers the essential behavior: what it does, what it verifies, and what it returns. It does not mention prerequisites or edge cases, but given the tool's simplicity and the annotations, this is adequately complete. The presence of an output schema reduces the need to describe return structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has only one parameter (project_id) with a regex pattern, but the schema description coverage is 0%, meaning no descriptive text in the schema. The description only says 'by ID,' which barely adds meaning beyond the parameter name itself. It does not explain the format, purpose, or constraints beyond what the pattern already implies, so the description carries minimal additional semantic weight.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Reopen') and identifies the resource ('server-created project') along with the identifier type. It also mentions two concrete outcomes (verifying committed sources and returning revision), making the tool's purpose unambiguous and distinct from siblings like project_inspect or project_create.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by specifying 'server-created project,' which suggests it is not for locally created ones, but it does not explicitly contrast with alternatives. There is no guidance on when to choose project_open over project_inspect or project_update, leaving the agent to infer the distinction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

project_updateB

Atomically update metadata, brief or decision journal. Requires expected_revision. UPM changes on nonempty fonts fail.

ParametersJSON Schema
NameRequiredDescriptionDefault
briefNo
metricsNo
summaryNo
decisionNo
metadataNo
project_idYes
design_specNo
expected_revisionYes
remove_reference_idsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (not read-only, not idempotent, not destructive), so the bar is lower. The description adds real context beyond them: atomicity of the operation, the optimistic-concurrency requirement of expected_revision, and a concrete failure condition ('UPM changes on nonempty fonts fail'). It stops short of saying what happens on revision mismatch or whether omitted fields are cleared.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the precondition, then the failure caveat. Zero padding. Slight deduction because 'UPM' is used as undefined jargon that an agent cannot map to units_per_em without schema inspection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a complex 9-parameter mutation tool with 0% schema coverage, and the description covers only a fraction of the input surface. The presence of an output schema removes the need to explain return values, but the missing guidance on the remaining update domains, revision-mismatch behavior, and field-clearing semantics leaves the definition under-specified for its complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 9 parameters, several of them deeply nested objects, so the description must carry the burden. It names only three of the update domains (metadata, brief, decision) and leaves design_spec, metrics, summary, remove_reference_ids, project_id, and expected_revision format/semantics unexplained. Partial compensation at best.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Atomically update metadata, brief or decision journal.' An agent can tell this is the mutation counterpart to project_create/project_open/project_inspect without opening a schema. It does not, however, enumerate the full set of updatable surfaces (metrics, design_spec, summary, remove_reference_ids) or name a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only usage guidance is the precondition 'Requires expected_revision.' There is no statement of when to prefer this over project_inspect, project_open, or history_restore, and no guidance on partial vs full updates. The agent is left to infer the workflow context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

proof_reviewA

Record an agent's visual review of immutable render report_uris from an exact revision. Use verdict=revise for defects; accepted intentional findings require their finding_id and a reason. Does not alter font sources or assert human approval. Inspect actual images before calling.

ParametersJSON Schema
NameRequiredDescriptionDefault
verdictYes
revisionYes
project_idYes
proof_urisYes
observationYes
resolutionsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give the generic flags (readOnlyHint=false, destructiveHint=false, idempotentHint=false); the description adds real behavioral context by stating the review is recorded against 'immutable' revision-bound report URIs and that it 'Does not alter font sources or assert human approval,' which sets expectations about side effects and scope of authority. It omits that repeat calls are non-idempotent (new records), which the annotations imply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action, then verdict rules, then the boundary statement. No filler; every sentence carries information, though the final two clauses are slightly compressed and could read ambiguously.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a non-read-only recording tool with an output schema present, the description covers the precondition (inspect images first), the verdict-dependent requirements, and what it does not do (no font-source mutation, no human approval claim). It is nearly complete, with only the non-idempotent recording behavior and observation input constraints unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden. It does explain the verdict semantics and the finding_id/reason requirement for resolutions, and ties proof_uris and revision together ('immutable render report_uris from an exact revision'). However, project_id, observation, and the array/length constraints (maxItems 8, minLength 12/20, hex patterns) are left entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Record an agent's visual review of immutable render report_uris from an exact revision.' This clearly separates it from siblings like render_proof or font_validate, though it never names an adjacent tool explicitly, so an agent must infer the pairing with render_proof.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives actionable conditions: 'Use verdict=revise for defects', 'accepted intentional findings require their finding_id and a reason', and the precondition 'Inspect actual images before calling.' That is clear when-to-use guidance, but there is no exclusion (e.g., when not to use this versus re-rendering the proof) and no mention of alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reference_importA

Import a bounded single-frame PNG from workspace/inbox as an immutable drawing reference. image_to_font maps image pixels (top-left, Y down) to font units (baseline, Y up). Requires expected_revision. No tracing or automatic rescaling; use reference_id with render_glyph.

ParametersJSON Schema
NameRequiredDescriptionDefault
cropNo
labelNo
replaceNo
summaryNo
glyph_idYes
image_modeNoinline
project_idYes
source_pathYes
reference_idYes
image_to_fontYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only tell the agent it is a non-read-only, non-destructive, non-idempotent operation. The description adds real behavioral context not in structured fields: the image_to_font pixel-to-font-unit convention (top-left, Y down → baseline, Y up), the immutability of the resulting reference, and the concurrency requirement (expected_revision). It omits the effect of `replace` and image_mode, but adds substantial value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences with the core action front-loaded and constraints following. No filler, though the mapping sentence and the trailing guidance could be split more clearly for scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, and annotations cover the safety profile. Still, for a mutation tool with 11 mostly-undocumented parameters, the description leaves gaps (crop semantics, replace behavior, image_mode) that an agent must guess at.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 11 parameters, so the description must compensate. It usefully explains image_to_font and flags expected_revision, but leaves crop, label, replace, summary, image_mode, source_path, glyph_id and reference_id entirely undocumented, which is most of the surface.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Import), resource (bounded single-frame PNG), source location (workspace/inbox) and its nature (immutable drawing reference). An agent can distinguish this from siblings like glyph_edit or render_glyph without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It points forward ("use reference_id with render_glyph") and excludes behaviors ("No tracing or automatic rescaling"), which is useful. However, it never says when to choose this import over other workflows or what prerequisites/preconditions apply beyond requiring expected_revision.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_glyphC

Persist and return PNG image content from the selected UFO revision, with optional guides/handles. Comparison uses the same frame.

ParametersJSON Schema
NameRequiredDescriptionDefault
widthNo
detailNosummary
guidesNo
heightNo
pointsNo
glyph_idYes
revisionNo
master_idNodefault
image_modeNoinline
project_idYes
measurementsNo
reference_idNo
comparison_modeNooverlay
compare_revisionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and non-idempotent, and 'Persist' is consistent with a write, so no contradiction. However, with 14 parameters the description does not explain what persisting entails (caching, overwrite, storage cost), whether it requires an open project, or what the comparison frame constraint actually means operationally.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with verb and resource, no filler. The second sentence is terse but carries a real constraint about comparison framing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter tool with zero schema descriptions, no output-schema explanation needed (output schema exists), the description is far too thin to let an agent call it confidently without reading every property.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% across 14 parameters, so the description must compensate but only touches guides/handles and comparison. Width, height, detail, master_id, image_mode, measurements, revision, and comparison_mode/reference_id/compare_revision are all left unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair (persist and return) and resource (PNG image content from the selected UFO revision), so an agent can tell it renders glyphs to images. It does not differentiate itself from siblings like render_text or render_proof, which also produce rendered output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no mention of alternatives (render_text, render_proof, glyph_get), and no indication of prerequisites such as an open project or valid revision. The only hint is that comparison reuses the same frame, which is a constraint rather than a selection rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_proofA

Render up to 32 glyphs at one common scale, optionally comparing revisions. Missing glyphs are explicit placeholders; use render_text separately for shaped words.

ParametersJSON Schema
NameRequiredDescriptionDefault
detailNosummary
guidesNo
pointsNo
columnsNo
revisionNo
glyph_idsYes
master_idNodefault
cell_widthNo
image_modeNoinline
project_idYes
cell_heightNo
compare_revisionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide no meaningful safety hints, so the description carries the burden. It discloses useful behavior beyond the name: missing glyphs become explicit placeholders, revisions can be compared, and all glyphs share one scale. This adds practical expectations without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences deliver the core capability, key limits, a behavioral guarantee, and a routing alternative. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter tool with 0% schema description coverage, the description only partially covers the invocation surface. The top-level purpose and the most important differentiation are clear, and an output schema exists, but several parameters still lack guidance. This is adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It captures the central parameter meanings: glyph count ('up to 32 glyphs'), unified scaling ('one common scale'), and revision comparison. However, it leaves several parameters unspecified (detail, guides, points, columns, master_id, image_mode, cell dimensions), relying on schema names and enums.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Render'), a bounded resource ('up to 32 glyphs'), and a distinguishing mode ('one common scale, optionally comparing revisions'). It also explicitly separates itself from render_text for shaped words, which helps distinguish it from a close sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly says to use render_text for shaped words instead, an explicit when-not with an alternative. However, it does not explicitly mention render_glyph for single-glyph rendering or other alternatives, so some usage context is left implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_textB

Compile the revision, shape with HarfBuzz and return FreeType PNGs. For variable fonts, location maps axis tags to values; omitted axes use defaults. Missing Unicode is reported. Optional same-conditions revision comparison.

ParametersJSON Schema
NameRequiredDescriptionDefault
darkNo
kernNo
textYes
sizesNo
widthNo
detailNosummary
locationNo
revisionNo
image_modeNoinline
project_idYes
compare_revisionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false (readOnlyHint, destructiveHint, idempotentHint), providing no safety profile. The description adds some behavioral context: it compiles the revision, shapes with HarfBuzz, returns PNGs, reports missing Unicode, and supports optional comparison. However, it doesn't clarify side effects (e.g., whether compiling modifies state) or error behavior. Given the annotations are uninformative, the description partially compensates but leaves gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the primary action. It efficiently covers key behaviors without excess verbosity. The structure is clean, though it omits crucial parameter details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 11 parameters, no schema descriptions, and an output schema present, the description is far from complete. It fails to explain the meaning of most parameters, their defaults, or relationships. The description covers only a fraction of what an agent needs to correctly invoke the tool, especially given the absence of schema descriptions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain parameters. It only touches on location (axis tags and defaults) and implicitly on compare_revision (same-conditions comparison). The remaining nine parameters (dark, kern, sizes, width, detail, image_mode, revision, project_id, text) are not explained at all. This is a significant gap for an 11-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (compile, shape, return) and resource (text rendering), and mentions key behaviors like variable font support and missing Unicode reporting. While it doesn't explicitly distinguish from render_glyph, the text-focused purpose is clear and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this tool is for rendering text (as opposed to render_glyph for single glyphs) but provides no explicit when-to-use or when-not-to-use guidance. It mentions an optional comparison feature but doesn't specify conditions for using it. No exclusions or alternatives are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spacing_editA

Atomically set advances, side bearings, kerning groups or pairs in master_id (default: 'default'). Bearings move outlines; advances do not.

ParametersJSON Schema
NameRequiredDescriptionDefault
summaryNo
master_idNodefault
operationsYes
project_idYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a non-read-only, non-idempotent mutation. The description adds two valuable behavioral details: atomicity (all-or-nothing) and the distinction that bearings move outlines while advances do not. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (two sentences) and front-loads the atomicity and scope. The key behavioral distinction is delivered efficiently without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with four operation types and atomic semantics, the description covers the core purpose and one behavioral nuance but omits details like batching behavior, the role of expected_revision (optimistic locking), and failure handling. The output schema may clarify return values, but the description itself leaves gaps for a complex mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It only names the four operation types (advances, bearings, kern pairs/groups) but does not explain fields like 'left', 'right', 'value', or 'glyph_id'. The schema itself provides no descriptions, leaving the agent to infer field meanings from names alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action ('Atomically set') and resources (advances, side bearings, kerning groups or pairs). It also specifies the default master_id, making the purpose unambiguous and distinct from sibling editing tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for spacing adjustments but does not explicitly compare with alternatives like glyph_edit or font_edit, nor does it state when not to use this tool. There is no exclusion or routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

variable_configureC

Configure continuous axes and masters in this project. Master 'default' is the existing source at the default location. New IDs clone it; existing IDs keep their drawings; omitted IDs are removed in a new revision. Edit masters with master_id. Compatibility is checked at build/validation time.

ParametersJSON Schema
NameRequiredDescriptionDefault
summaryNo
variationYes
project_idYes
expected_revisionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
dataNo
errorNo
changedNo
summaryYes
revisionNo
warningsNo
project_idNo

TDQS

C2.4/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses behaviors like new IDs cloning the default master, existing IDs keeping drawings, and omitted IDs being removed, but the removal behavior contradicts the annotation destructiveHint=false. This is a significant inconsistency, so the description fails to provide accurate behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, consisting of three sentences with no fluff. It front-loads the purpose and adds behavioral details efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complex schema with nested objects and many constraints, the description lacks guidance on how to specify axes and masters, the meaning of continuous axes, and the relationship between parameters. It mentions project context but not enough for an agent to construct a valid variation object. The output schema exists so return values are not needed, but input guidance is insufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description provides no parameter information. With schema description coverage at 0%, the description must compensate, but it does not explain any of the parameters, including required fields like project_id, expected_revision, or the variation structure.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool configures continuous axes and masters in a project, which is a specific resource. It distinguishes from generic update tools by focusing on variable font configuration, though it doesn't explicitly compare to siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like project_update or font_edit. The description implies usage for configuring axes and masters but doesn't state conditions or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updatesv0.6.0
    • Changedfont_analyze1 field changed
      • addedInput schema / properties / interpolation
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
    • Changedfont_build2 fields changed
      • addedInput schema / properties / purpose
        Added value: +{
        +  "default": "proof",
        +  "enum": [
        +    "proof",
        +    "release"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / review_uris
        Added value: +{
        +  "items": {
        +    "maxLength": 250,
        +    "type": "string"
        +  },
        +  "maxItems": 128,
        +  "type": "array"
        +}
    • Changedfont_edit9 fields changed
      • addedInput schema / $defs / DetachStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "detach_stroke_network",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / detach_stroke_network
        Added value: +"#/$defs/DetachStrokeNetwork"
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / stroke_network
        Added value: +"#/$defs/SetStrokeNetwork"
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / update_stroke_network
        Added value: +"#/$defs/UpdateStrokeNetwork"
      • changedInput schema / $defs / GlyphChange / properties / operations / items / oneOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/PutContour"
        -  },
        -  {
        -    "$ref": "#/$defs/MovePoint"
        -  },
        -  {
        -    "$ref": "#/$defs/MoveHandle"
        -  },
        -  {
        -    "$ref": "#/$defs/SetSmooth"
        -  },
        -  {
        -    "$ref": "#/$defs/DetachComposition"
        -  },
        -  {
        -    "$ref": "#/$defs/Transform"
        -  },
        -  {
        -    "$ref": "#/$defs/PutComponent"
        -  },
        -  {
        -    "$ref": "#/$defs/PutAnchor"
        -  },
        -  {
        -    "$ref": "#/$defs/Remove"
        -  },
        -  {
        -    "$ref": "#/$defs/SetUnicodes"
        -  },
        -  {
        -    "$ref": "#/$defs/ReplaceGlyph"
        -  },
        -  {
        -    "$ref": "#/$defs/FilledPath"
        -  },
        -  {
        -    "$ref": "#/$defs/StrokePath"
        -  },
        -  {
        -    "$ref": "#/$defs/Primitive"
        -  },
        -  {
        -    "$ref": "#/$defs/Duplicate"
        -  },
        -  {
        -    "$ref": "#/$defs/ComposeAccent"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/PutContour"
        +  },
        +  {
        +    "$ref": "#/$defs/MovePoint"
        +  },
        +  {
        +    "$ref": "#/$defs/MoveHandle"
        +  },
        +  {
        +    "$ref": "#/$defs/SetSmooth"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachComposition"
        +  },
        +  {
        +    "$ref": "#/$defs/Transform"
        +  },
        +  {
        +    "$ref": "#/$defs/PutComponent"
        +  },
        +  {
        +    "$ref": "#/$defs/PutAnchor"
        +  },
        +  {
        +    "$ref": "#/$defs/Remove"
        +  },
        +  {
        +    "$ref": "#/$defs/SetUnicodes"
        +  },
        +  {
        +    "$ref": "#/$defs/ReplaceGlyph"
        +  },
        +  {
        +    "$ref": "#/$defs/FilledPath"
        +  },
        +  {
        +    "$ref": "#/$defs/StrokePath"
        +  },
        +  {
        +    "$ref": "#/$defs/SetStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/UpdateStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/Primitive"
        +  },
        +  {
        +    "$ref": "#/$defs/Duplicate"
        +  },
        +  {
        +    "$ref": "#/$defs/ComposeAccent"
        +  }
        +]
      • addedInput schema / $defs / NetworkStroke
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "cap": {
        +      "default": "butt",
        +      "enum": [
        +        "round",
        +        "butt",
        +        "square"
        +      ],
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,15}$",
        +      "type": "string"
        +    },
        +    "join": {
        +      "default": "miter",
        +      "enum": [
        +        "round",
        +        "bevel",
        +        "miter"
        +      ],
        +      "type": "string"
        +    },
        +    "path": {
        +      "maxLength": 16000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "width_parameter": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "path",
        +    "width_parameter"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / SetStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "network": {
        +      "$ref": "#/$defs/StrokeNetwork"
        +    },
        +    "op": {
        +      "const": "stroke_network",
        +      "type": "string"
        +    },
        +    "replace": {
        +      "default": false,
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "network"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / StrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "default": 600,
        +      "maximum": 16000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "horizontal_scale": {
        +      "default": 1,
        +      "exclusiveMinimum": 0,
        +      "maximum": 4,
        +      "type": "number"
        +    },
        +    "origin_x": {
        +      "default": 0,
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "parameters": {
        +      "maxProperties": 16,
        +      "minProperties": 1,
        +      "patternProperties": {
        +        "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$": {
        +          "exclusiveMinimum": 0,
        +          "maximum": 2000,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "strokes": {
        +      "items": {
        +        "$ref": "#/$defs/NetworkStroke"
        +      },
        +      "maxItems": 16,
        +      "minItems": 1,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "parameters",
        +    "strokes"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / UpdateStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "anyOf": [
        +        {
        +          "maximum": 16000,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "horizontal_scale": {
        +      "anyOf": [
        +        {
        +          "exclusiveMinimum": 0,
        +          "maximum": 4,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "op": {
        +      "const": "update_stroke_network",
        +      "type": "string"
        +    },
        +    "parameters": {
        +      "maxProperties": 16,
        +      "patternProperties": {
        +        "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$": {
        +          "exclusiveMinimum": 0,
        +          "maximum": 2000,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
    • Addedfont_release_check
    • Changedglyph_edit9 fields changed
      • addedInput schema / $defs / DetachStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "detach_stroke_network",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / NetworkStroke
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "cap": {
        +      "default": "butt",
        +      "enum": [
        +        "round",
        +        "butt",
        +        "square"
        +      ],
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,15}$",
        +      "type": "string"
        +    },
        +    "join": {
        +      "default": "miter",
        +      "enum": [
        +        "round",
        +        "bevel",
        +        "miter"
        +      ],
        +      "type": "string"
        +    },
        +    "path": {
        +      "maxLength": 16000,
        +      "minLength": 1,
        +      "type": "string"
        +    },
        +    "width_parameter": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "path",
        +    "width_parameter"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / SetStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "network": {
        +      "$ref": "#/$defs/StrokeNetwork"
        +    },
        +    "op": {
        +      "const": "stroke_network",
        +      "type": "string"
        +    },
        +    "replace": {
        +      "default": false,
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "network"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / StrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "default": 600,
        +      "maximum": 16000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "horizontal_scale": {
        +      "default": 1,
        +      "exclusiveMinimum": 0,
        +      "maximum": 4,
        +      "type": "number"
        +    },
        +    "origin_x": {
        +      "default": 0,
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "parameters": {
        +      "maxProperties": 16,
        +      "minProperties": 1,
        +      "patternProperties": {
        +        "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$": {
        +          "exclusiveMinimum": 0,
        +          "maximum": 2000,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "strokes": {
        +      "items": {
        +        "$ref": "#/$defs/NetworkStroke"
        +      },
        +      "maxItems": 16,
        +      "minItems": 1,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "parameters",
        +    "strokes"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / UpdateStrokeNetwork
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "anyOf": [
        +        {
        +          "maximum": 16000,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "horizontal_scale": {
        +      "anyOf": [
        +        {
        +          "exclusiveMinimum": 0,
        +          "maximum": 4,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "op": {
        +      "const": "update_stroke_network",
        +      "type": "string"
        +    },
        +    "parameters": {
        +      "maxProperties": 16,
        +      "patternProperties": {
        +        "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$": {
        +          "exclusiveMinimum": 0,
        +          "maximum": 2000,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / operations / items / discriminator / mapping / detach_stroke_network
        Added value: +"#/$defs/DetachStrokeNetwork"
      • addedInput schema / properties / operations / items / discriminator / mapping / stroke_network
        Added value: +"#/$defs/SetStrokeNetwork"
      • addedInput schema / properties / operations / items / discriminator / mapping / update_stroke_network
        Added value: +"#/$defs/UpdateStrokeNetwork"
      • changedInput schema / properties / operations / items / oneOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/PutContour"
        -  },
        -  {
        -    "$ref": "#/$defs/MovePoint"
        -  },
        -  {
        -    "$ref": "#/$defs/MoveHandle"
        -  },
        -  {
        -    "$ref": "#/$defs/SetSmooth"
        -  },
        -  {
        -    "$ref": "#/$defs/DetachComposition"
        -  },
        -  {
        -    "$ref": "#/$defs/Transform"
        -  },
        -  {
        -    "$ref": "#/$defs/PutComponent"
        -  },
        -  {
        -    "$ref": "#/$defs/PutAnchor"
        -  },
        -  {
        -    "$ref": "#/$defs/Remove"
        -  },
        -  {
        -    "$ref": "#/$defs/SetUnicodes"
        -  },
        -  {
        -    "$ref": "#/$defs/ReplaceGlyph"
        -  },
        -  {
        -    "$ref": "#/$defs/FilledPath"
        -  },
        -  {
        -    "$ref": "#/$defs/StrokePath"
        -  },
        -  {
        -    "$ref": "#/$defs/Primitive"
        -  },
        -  {
        -    "$ref": "#/$defs/Duplicate"
        -  },
        -  {
        -    "$ref": "#/$defs/ComposeAccent"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/PutContour"
        +  },
        +  {
        +    "$ref": "#/$defs/MovePoint"
        +  },
        +  {
        +    "$ref": "#/$defs/MoveHandle"
        +  },
        +  {
        +    "$ref": "#/$defs/SetSmooth"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachComposition"
        +  },
        +  {
        +    "$ref": "#/$defs/Transform"
        +  },
        +  {
        +    "$ref": "#/$defs/PutComponent"
        +  },
        +  {
        +    "$ref": "#/$defs/PutAnchor"
        +  },
        +  {
        +    "$ref": "#/$defs/Remove"
        +  },
        +  {
        +    "$ref": "#/$defs/SetUnicodes"
        +  },
        +  {
        +    "$ref": "#/$defs/ReplaceGlyph"
        +  },
        +  {
        +    "$ref": "#/$defs/FilledPath"
        +  },
        +  {
        +    "$ref": "#/$defs/StrokePath"
        +  },
        +  {
        +    "$ref": "#/$defs/SetStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/UpdateStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachStrokeNetwork"
        +  },
        +  {
        +    "$ref": "#/$defs/Primitive"
        +  },
        +  {
        +    "$ref": "#/$defs/Duplicate"
        +  },
        +  {
        +    "$ref": "#/$defs/ComposeAccent"
        +  }
        +]
    • Changedproject_create15 fields changed
      • addedInput schema / $defs / DesignRegion
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "A declared area in normalized visible bounds; useful for non-Latin and alternate anatomy.",
        +  "properties": {
        +    "bounds": {
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "prefixItems": [
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "anyOf": [
        +        {
        +          "maxProperties": 4,
        +          "patternProperties": {
        +            "^[A-Za-z][A-Za-z0-9]{3}$": {
        +              "maximum": 32767,
        +              "minimum": -32768,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "minimum_samples": {
        +      "default": 2,
        +      "maximum": 17,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "role": {
        +      "enum": [
        +        "stem",
        +        "branch",
        +        "junction",
        +        "counter",
        +        "curve",
        +        "terminal"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "bounds",
        +    "role"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / DesignSpec / properties / glyph_origins
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/GlyphOrigin"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / regions
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/DesignRegion"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / stroke_profiles
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/StrokeProfile"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / usage_texts
        Added value: +{
        +  "items": {
        +    "maxLength": 80,
        +    "minLength": 2,
        +    "type": "string"
        +  },
        +  "maxItems": 64,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / variation_probes
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/VariationProbe"
        +  },
        +  "maxItems": 32,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / variation_profiles
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/VariationProfile"
        +  },
        +  "maxItems": 128,
        +  "type": "array"
        +}
      • addedInput schema / $defs / GlyphOrigin
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "observation": {
        +      "maxLength": 1000,
        +      "minLength": 20,
        +      "type": "string"
        +    },
        +    "reference_ids": {
        +      "items": {
        +        "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +        "type": "string"
        +      },
        +      "maxItems": 16,
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "observed",
        +        "extrapolated",
        +        "original"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "glyph_id",
        +    "status",
        +    "observation"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / MetricRule / properties / location
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / MetricRule / properties / master_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProbe / properties / location
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProbe / properties / master_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProfile
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Sample perpendicular to a centerline; measure ink or a bounded counter, in font units.",
        +  "properties": {
        +    "end": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "anyOf": [
        +        {
        +          "maxProperties": 4,
        +          "patternProperties": {
        +            "^[A-Za-z][A-Za-z0-9]{3}$": {
        +              "maximum": 32767,
        +              "minimum": -32768,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "max_ratio": {
        +      "anyOf": [
        +        {
        +          "maximum": 100,
        +          "minimum": 1,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "maximum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "region": {
        +      "default": "ink",
        +      "enum": [
        +        "ink",
        +        "counter"
        +      ],
        +      "type": "string"
        +    },
        +    "samples": {
        +      "default": 5,
        +      "maximum": 17,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "start",
        +    "end",
        +    "minimum",
        +    "maximum"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / VariationProbe
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Sample a declared stroke across an axis; this is not an optical weight estimate.",
        +  "properties": {
        +    "axis": {
        +      "default": "horizontal",
        +      "enum": [
        +        "horizontal",
        +        "vertical"
        +      ],
        +      "type": "string"
        +    },
        +    "axis_tag": {
        +      "pattern": "^[A-Za-z][A-Za-z0-9]{3}$",
        +      "type": "string"
        +    },
        +    "direction": {
        +      "default": "nondecreasing",
        +      "enum": [
        +        "nondecreasing",
        +        "nonincreasing"
        +      ],
        +      "type": "string"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "minimum_change": {
        +      "default": 0,
        +      "maximum": 4000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "position": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "span_index": {
        +      "default": 0,
        +      "maximum": 63,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    },
        +    "values": {
        +      "items": {
        +        "maximum": 32767,
        +        "minimum": -32768,
        +        "type": "number"
        +      },
        +      "maxItems": 9,
        +      "minItems": 2,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "position",
        +    "axis_tag",
        +    "values"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / VariationProfile
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "axis_tag": {
        +      "pattern": "^[A-Za-z][A-Za-z0-9]{3}$",
        +      "type": "string"
        +    },
        +    "direction": {
        +      "default": "nondecreasing",
        +      "enum": [
        +        "nondecreasing",
        +        "nonincreasing"
        +      ],
        +      "type": "string"
        +    },
        +    "end": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "max_ratio": {
        +      "anyOf": [
        +        {
        +          "maximum": 100,
        +          "minimum": 1,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "maximum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum_change": {
        +      "default": 0,
        +      "maximum": 4000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "region": {
        +      "default": "ink",
        +      "enum": [
        +        "ink",
        +        "counter"
        +      ],
        +      "type": "string"
        +    },
        +    "samples": {
        +      "default": 5,
        +      "maximum": 17,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    },
        +    "values": {
        +      "items": {
        +        "maximum": 32767,
        +        "minimum": -32768,
        +        "type": "number"
        +      },
        +      "maxItems": 9,
        +      "minItems": 2,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "start",
        +    "end",
        +    "minimum",
        +    "maximum",
        +    "axis_tag",
        +    "values"
        +  ],
        +  "type": "object"
        +}
    • Changedproject_inspect3 fields changed
      • addedInput schema / properties / glyph_ids
        Added value: +{
        +  "items": {
        +    "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +    "type": "string"
        +  },
        +  "maxItems": 32,
        +  "type": "array"
        +}
      • addedInput schema / properties / master_id
        Added value: +{
        +  "default": "default",
        +  "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / sections
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "enum": [
        +          "metadata",
        +          "design",
        +          "glyphs",
        +          "spacing",
        +          "compositions",
        +          "history"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 6,
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Changedproject_update15 fields changed
      • addedInput schema / $defs / DesignRegion
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "A declared area in normalized visible bounds; useful for non-Latin and alternate anatomy.",
        +  "properties": {
        +    "bounds": {
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "prefixItems": [
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 1,
        +          "minimum": 0,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "anyOf": [
        +        {
        +          "maxProperties": 4,
        +          "patternProperties": {
        +            "^[A-Za-z][A-Za-z0-9]{3}$": {
        +              "maximum": 32767,
        +              "minimum": -32768,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "minimum_samples": {
        +      "default": 2,
        +      "maximum": 17,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "role": {
        +      "enum": [
        +        "stem",
        +        "branch",
        +        "junction",
        +        "counter",
        +        "curve",
        +        "terminal"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "bounds",
        +    "role"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / DesignSpec / properties / glyph_origins
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/GlyphOrigin"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / regions
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/DesignRegion"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / stroke_profiles
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/StrokeProfile"
        +  },
        +  "maxItems": 512,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / usage_texts
        Added value: +{
        +  "items": {
        +    "maxLength": 80,
        +    "minLength": 2,
        +    "type": "string"
        +  },
        +  "maxItems": 64,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / variation_probes
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/VariationProbe"
        +  },
        +  "maxItems": 32,
        +  "type": "array"
        +}
      • addedInput schema / $defs / DesignSpec / properties / variation_profiles
        Added value: +{
        +  "items": {
        +    "$ref": "#/$defs/VariationProfile"
        +  },
        +  "maxItems": 128,
        +  "type": "array"
        +}
      • addedInput schema / $defs / GlyphOrigin
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "observation": {
        +      "maxLength": 1000,
        +      "minLength": 20,
        +      "type": "string"
        +    },
        +    "reference_ids": {
        +      "items": {
        +        "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +        "type": "string"
        +      },
        +      "maxItems": 16,
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "observed",
        +        "extrapolated",
        +        "original"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "glyph_id",
        +    "status",
        +    "observation"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / MetricRule / properties / location
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / MetricRule / properties / master_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProbe / properties / location
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProbe / properties / master_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / $defs / StrokeProfile
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Sample perpendicular to a centerline; measure ink or a bounded counter, in font units.",
        +  "properties": {
        +    "end": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "anyOf": [
        +        {
        +          "maxProperties": 4,
        +          "patternProperties": {
        +            "^[A-Za-z][A-Za-z0-9]{3}$": {
        +              "maximum": 32767,
        +              "minimum": -32768,
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "max_ratio": {
        +      "anyOf": [
        +        {
        +          "maximum": 100,
        +          "minimum": 1,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "maximum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "region": {
        +      "default": "ink",
        +      "enum": [
        +        "ink",
        +        "counter"
        +      ],
        +      "type": "string"
        +    },
        +    "samples": {
        +      "default": 5,
        +      "maximum": 17,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "start",
        +    "end",
        +    "minimum",
        +    "maximum"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / VariationProbe
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Sample a declared stroke across an axis; this is not an optical weight estimate.",
        +  "properties": {
        +    "axis": {
        +      "default": "horizontal",
        +      "enum": [
        +        "horizontal",
        +        "vertical"
        +      ],
        +      "type": "string"
        +    },
        +    "axis_tag": {
        +      "pattern": "^[A-Za-z][A-Za-z0-9]{3}$",
        +      "type": "string"
        +    },
        +    "direction": {
        +      "default": "nondecreasing",
        +      "enum": [
        +        "nondecreasing",
        +        "nonincreasing"
        +      ],
        +      "type": "string"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "minimum_change": {
        +      "default": 0,
        +      "maximum": 4000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "position": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "span_index": {
        +      "default": 0,
        +      "maximum": 63,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    },
        +    "values": {
        +      "items": {
        +        "maximum": 32767,
        +        "minimum": -32768,
        +        "type": "number"
        +      },
        +      "maxItems": 9,
        +      "minItems": 2,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "position",
        +    "axis_tag",
        +    "values"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / VariationProfile
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "axis_tag": {
        +      "pattern": "^[A-Za-z][A-Za-z0-9]{3}$",
        +      "type": "string"
        +    },
        +    "direction": {
        +      "default": "nondecreasing",
        +      "enum": [
        +        "nondecreasing",
        +        "nonincreasing"
        +      ],
        +      "type": "string"
        +    },
        +    "end": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "location": {
        +      "maxProperties": 4,
        +      "patternProperties": {
        +        "^[A-Za-z][A-Za-z0-9]{3}$": {
        +          "maximum": 32767,
        +          "minimum": -32768,
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "master_id": {
        +      "anyOf": [
        +        {
        +          "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "max_ratio": {
        +      "anyOf": [
        +        {
        +          "maximum": 100,
        +          "minimum": 1,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "maximum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "minimum_change": {
        +      "default": 0,
        +      "maximum": 4000,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "region": {
        +      "default": "ink",
        +      "enum": [
        +        "ink",
        +        "counter"
        +      ],
        +      "type": "string"
        +    },
        +    "samples": {
        +      "default": 5,
        +      "maximum": 17,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maxItems": 2,
        +      "minItems": 2,
        +      "prefixItems": [
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    },
        +    "values": {
        +      "items": {
        +        "maximum": 32767,
        +        "minimum": -32768,
        +        "type": "number"
        +      },
        +      "maxItems": 9,
        +      "minItems": 2,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "start",
        +    "end",
        +    "minimum",
        +    "maximum",
        +    "axis_tag",
        +    "values"
        +  ],
        +  "type": "object"
        +}
    • Addedproof_review
    • Changedreference_import1 field changed
      • addedInput schema / properties / crop
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maxItems": 4,
        +      "minItems": 4,
        +      "prefixItems": [
        +        {
        +          "maximum": 2048,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        {
        +          "maximum": 2048,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        {
        +          "maximum": 2048,
        +          "minimum": 1,
        +          "type": "integer"
        +        },
        +        {
        +          "maximum": 2048,
        +          "minimum": 1,
        +          "type": "integer"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Changedrender_glyph2 fields changed
      • addedInput schema / properties / comparison_mode
        Added value: +{
        +  "default": "overlay",
        +  "enum": [
        +    "overlay",
        +    "difference"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / measurements
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
  2. 9 tool updatesv0.5.0
    • Addedfont_analyze
    • Changedfont_build1 field changed
      • addedInput schema / properties / require_design_checks
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
    • Changedfont_edit9 fields changed
      • addedInput schema / $defs / ComposeAccent / properties / auto_align
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / $defs / DetachComposition
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "detach_composition",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / detach_composition
        Added value: +"#/$defs/DetachComposition"
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / move_handle
        Added value: +"#/$defs/MoveHandle"
      • addedInput schema / $defs / GlyphChange / properties / operations / items / discriminator / mapping / set_smooth
        Added value: +"#/$defs/SetSmooth"
      • changedInput schema / $defs / GlyphChange / properties / operations / items / oneOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/PutContour"
        -  },
        -  {
        -    "$ref": "#/$defs/MovePoint"
        -  },
        -  {
        -    "$ref": "#/$defs/Transform"
        -  },
        -  {
        -    "$ref": "#/$defs/PutComponent"
        -  },
        -  {
        -    "$ref": "#/$defs/PutAnchor"
        -  },
        -  {
        -    "$ref": "#/$defs/Remove"
        -  },
        -  {
        -    "$ref": "#/$defs/SetUnicodes"
        -  },
        -  {
        -    "$ref": "#/$defs/ReplaceGlyph"
        -  },
        -  {
        -    "$ref": "#/$defs/FilledPath"
        -  },
        -  {
        -    "$ref": "#/$defs/StrokePath"
        -  },
        -  {
        -    "$ref": "#/$defs/Primitive"
        -  },
        -  {
        -    "$ref": "#/$defs/Duplicate"
        -  },
        -  {
        -    "$ref": "#/$defs/ComposeAccent"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/PutContour"
        +  },
        +  {
        +    "$ref": "#/$defs/MovePoint"
        +  },
        +  {
        +    "$ref": "#/$defs/MoveHandle"
        +  },
        +  {
        +    "$ref": "#/$defs/SetSmooth"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachComposition"
        +  },
        +  {
        +    "$ref": "#/$defs/Transform"
        +  },
        +  {
        +    "$ref": "#/$defs/PutComponent"
        +  },
        +  {
        +    "$ref": "#/$defs/PutAnchor"
        +  },
        +  {
        +    "$ref": "#/$defs/Remove"
        +  },
        +  {
        +    "$ref": "#/$defs/SetUnicodes"
        +  },
        +  {
        +    "$ref": "#/$defs/ReplaceGlyph"
        +  },
        +  {
        +    "$ref": "#/$defs/FilledPath"
        +  },
        +  {
        +    "$ref": "#/$defs/StrokePath"
        +  },
        +  {
        +    "$ref": "#/$defs/Primitive"
        +  },
        +  {
        +    "$ref": "#/$defs/Duplicate"
        +  },
        +  {
        +    "$ref": "#/$defs/ComposeAccent"
        +  }
        +]
      • addedInput schema / $defs / MoveHandle
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "mode": {
        +      "default": "aligned",
        +      "enum": [
        +        "aligned",
        +        "symmetric"
        +      ],
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "move_handle",
        +      "type": "string"
        +    },
        +    "point_id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "x": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "y": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "point_id",
        +    "x",
        +    "y"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / MovePoint / properties / preserve_handles
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / $defs / SetSmooth
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "set_smooth",
        +      "type": "string"
        +    },
        +    "point_id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "smooth": {
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "point_id",
        +    "smooth"
        +  ],
        +  "type": "object"
        +}
    • Changedglyph_edit9 fields changed
      • addedInput schema / $defs / ComposeAccent / properties / auto_align
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / $defs / DetachComposition
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "detach_composition",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / MoveHandle
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "mode": {
        +      "default": "aligned",
        +      "enum": [
        +        "aligned",
        +        "symmetric"
        +      ],
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "move_handle",
        +      "type": "string"
        +    },
        +    "point_id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "x": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "y": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "point_id",
        +    "x",
        +    "y"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / MovePoint / properties / preserve_handles
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / $defs / SetSmooth
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "op": {
        +      "const": "set_smooth",
        +      "type": "string"
        +    },
        +    "point_id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "smooth": {
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "point_id",
        +    "smooth"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / operations / items / discriminator / mapping / detach_composition
        Added value: +"#/$defs/DetachComposition"
      • addedInput schema / properties / operations / items / discriminator / mapping / move_handle
        Added value: +"#/$defs/MoveHandle"
      • addedInput schema / properties / operations / items / discriminator / mapping / set_smooth
        Added value: +"#/$defs/SetSmooth"
      • changedInput schema / properties / operations / items / oneOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/PutContour"
        -  },
        -  {
        -    "$ref": "#/$defs/MovePoint"
        -  },
        -  {
        -    "$ref": "#/$defs/Transform"
        -  },
        -  {
        -    "$ref": "#/$defs/PutComponent"
        -  },
        -  {
        -    "$ref": "#/$defs/PutAnchor"
        -  },
        -  {
        -    "$ref": "#/$defs/Remove"
        -  },
        -  {
        -    "$ref": "#/$defs/SetUnicodes"
        -  },
        -  {
        -    "$ref": "#/$defs/ReplaceGlyph"
        -  },
        -  {
        -    "$ref": "#/$defs/FilledPath"
        -  },
        -  {
        -    "$ref": "#/$defs/StrokePath"
        -  },
        -  {
        -    "$ref": "#/$defs/Primitive"
        -  },
        -  {
        -    "$ref": "#/$defs/Duplicate"
        -  },
        -  {
        -    "$ref": "#/$defs/ComposeAccent"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/PutContour"
        +  },
        +  {
        +    "$ref": "#/$defs/MovePoint"
        +  },
        +  {
        +    "$ref": "#/$defs/MoveHandle"
        +  },
        +  {
        +    "$ref": "#/$defs/SetSmooth"
        +  },
        +  {
        +    "$ref": "#/$defs/DetachComposition"
        +  },
        +  {
        +    "$ref": "#/$defs/Transform"
        +  },
        +  {
        +    "$ref": "#/$defs/PutComponent"
        +  },
        +  {
        +    "$ref": "#/$defs/PutAnchor"
        +  },
        +  {
        +    "$ref": "#/$defs/Remove"
        +  },
        +  {
        +    "$ref": "#/$defs/SetUnicodes"
        +  },
        +  {
        +    "$ref": "#/$defs/ReplaceGlyph"
        +  },
        +  {
        +    "$ref": "#/$defs/FilledPath"
        +  },
        +  {
        +    "$ref": "#/$defs/StrokePath"
        +  },
        +  {
        +    "$ref": "#/$defs/Primitive"
        +  },
        +  {
        +    "$ref": "#/$defs/Duplicate"
        +  },
        +  {
        +    "$ref": "#/$defs/ComposeAccent"
        +  }
        +]
    • Changedproject_create4 fields changed
      • addedInput schema / $defs / DesignSpec
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "digit_spacing": {
        +      "default": "unspecified",
        +      "enum": [
        +        "unspecified",
        +        "proportional",
        +        "tabular"
        +      ],
        +      "type": "string"
        +    },
        +    "digit_tolerance": {
        +      "default": 0.5,
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "metric_rules": {
        +      "items": {
        +        "$ref": "#/$defs/MetricRule"
        +      },
        +      "maxItems": 64,
        +      "type": "array"
        +    },
        +    "notes": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "protected_features": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "reference_glyphs": {
        +      "items": {
        +        "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +        "type": "string"
        +      },
        +      "maxItems": 64,
        +      "type": "array"
        +    },
        +    "required_characters": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "stroke_probes": {
        +      "items": {
        +        "$ref": "#/$defs/StrokeProbe"
        +      },
        +      "maxItems": 128,
        +      "type": "array"
        +    },
        +    "tangent_tolerance_degrees": {
        +      "default": 3,
        +      "exclusiveMinimum": 0,
        +      "maximum": 30,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / $defs / MetricRule
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Explicit equality targets, not inferred rules of beauty. All values are font units.",
        +  "properties": {
        +    "glyphs": {
        +      "items": {
        +        "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +        "type": "string"
        +      },
        +      "maxItems": 64,
        +      "minItems": 1,
        +      "type": "array"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "metric": {
        +      "enum": [
        +        "advance",
        +        "visible_width",
        +        "height",
        +        "left_bearing",
        +        "right_bearing"
        +      ],
        +      "type": "string"
        +    },
        +    "target": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "tolerance": {
        +      "default": 1,
        +      "maximum": 1000,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyphs",
        +    "metric",
        +    "target"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / StrokeProbe
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Measure a filled interval on a declared scanline; choose away from junctions.",
        +  "properties": {
        +    "axis": {
        +      "default": "horizontal",
        +      "enum": [
        +        "horizontal",
        +        "vertical"
        +      ],
        +      "type": "string"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "position": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "span_index": {
        +      "default": 0,
        +      "maximum": 63,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "target": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "position",
        +    "target"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / design_spec
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/DesignSpec"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Changedproject_update5 fields changed
      • addedInput schema / $defs / DesignSpec
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "digit_spacing": {
        +      "default": "unspecified",
        +      "enum": [
        +        "unspecified",
        +        "proportional",
        +        "tabular"
        +      ],
        +      "type": "string"
        +    },
        +    "digit_tolerance": {
        +      "default": 0.5,
        +      "maximum": 100,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    "metric_rules": {
        +      "items": {
        +        "$ref": "#/$defs/MetricRule"
        +      },
        +      "maxItems": 64,
        +      "type": "array"
        +    },
        +    "notes": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "protected_features": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "reference_glyphs": {
        +      "items": {
        +        "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +        "type": "string"
        +      },
        +      "maxItems": 64,
        +      "type": "array"
        +    },
        +    "required_characters": {
        +      "default": "",
        +      "maxLength": 4000,
        +      "type": "string"
        +    },
        +    "stroke_probes": {
        +      "items": {
        +        "$ref": "#/$defs/StrokeProbe"
        +      },
        +      "maxItems": 128,
        +      "type": "array"
        +    },
        +    "tangent_tolerance_degrees": {
        +      "default": 3,
        +      "exclusiveMinimum": 0,
        +      "maximum": 30,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / $defs / MetricRule
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Explicit equality targets, not inferred rules of beauty. All values are font units.",
        +  "properties": {
        +    "glyphs": {
        +      "items": {
        +        "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +        "type": "string"
        +      },
        +      "maxItems": 64,
        +      "minItems": 1,
        +      "type": "array"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "metric": {
        +      "enum": [
        +        "advance",
        +        "visible_width",
        +        "height",
        +        "left_bearing",
        +        "right_bearing"
        +      ],
        +      "type": "string"
        +    },
        +    "target": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "tolerance": {
        +      "default": 1,
        +      "maximum": 1000,
        +      "minimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyphs",
        +    "metric",
        +    "target"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / StrokeProbe
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Measure a filled interval on a declared scanline; choose away from junctions.",
        +  "properties": {
        +    "axis": {
        +      "default": "horizontal",
        +      "enum": [
        +        "horizontal",
        +        "vertical"
        +      ],
        +      "type": "string"
        +    },
        +    "glyph_id": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "id": {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "position": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "span_index": {
        +      "default": 0,
        +      "maximum": 63,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "target": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 4000,
        +      "type": "number"
        +    },
        +    "tolerance": {
        +      "default": 2,
        +      "maximum": 1000,
        +      "minimum": 0.5,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "glyph_id",
        +    "position",
        +    "target"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / design_spec
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/DesignSpec"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / remove_reference_ids
        Added value: +{
        +  "items": {
        +    "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +    "type": "string"
        +  },
        +  "maxItems": 64,
        +  "type": "array"
        +}
    • Addedreference_import
    • Changedrender_glyph1 field changed
      • addedInput schema / properties / reference_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Addedrender_proof
  3. 15 tool updatesv0.4.3
    • Changedfont_build13 fields changed
      • removedInput schema / properties / formats / title
        Removed value: -"Formats"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / title
        Removed value: -"Build"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Addedfont_edit
    • Changedfont_validate14 fields changed
      • removedInput schema / properties / corpus / title
        Removed value: -"Corpus"
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / title
        Removed value: -"Validate"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedglyph_edit81 fields changed
      • removedInput schema / $defs / Anchor / properties / id / title
        Removed value: -"Id"
      • removedInput schema / $defs / Anchor / properties / name / title
        Removed value: -"Name"
      • removedInput schema / $defs / Anchor / properties / x / title
        Removed value: -"X"
      • removedInput schema / $defs / Anchor / properties / y / title
        Removed value: -"Y"
      • removedInput schema / $defs / Anchor / title
        Removed value: -"Anchor"
      • removedInput schema / $defs / Component / properties / base / title
        Removed value: -"Base"
      • removedInput schema / $defs / Component / properties / id / title
        Removed value: -"Id"
      • removedInput schema / $defs / Component / properties / transform / title
        Removed value: -"Transform"
      • removedInput schema / $defs / Component / title
        Removed value: -"Component"
      • addedInput schema / $defs / ComposeAccent
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "base": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "base_anchor": {
        +      "default": "top",
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "mark": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    },
        +    "mark_anchor": {
        +      "default": "_top",
        +      "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "compose_accent",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "base",
        +    "mark"
        +  ],
        +  "type": "object"
        +}
      • removedInput schema / $defs / Contour / properties / id / title
        Removed value: -"Id"
      • removedInput schema / $defs / Contour / properties / points / title
        Removed value: -"Points"
      • removedInput schema / $defs / Contour / title
        Removed value: -"Contour"
      • addedInput schema / $defs / Duplicate
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "matrix": {
        +      "default": [
        +        1,
        +        0,
        +        0,
        +        1,
        +        0,
        +        0
        +      ],
        +      "maxItems": 6,
        +      "minItems": 6,
        +      "prefixItems": [
        +        {
        +          "maximum": 16,
        +          "minimum": -16,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16,
        +          "minimum": -16,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16,
        +          "minimum": -16,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16,
        +          "minimum": -16,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        },
        +        {
        +          "maximum": 16000,
        +          "minimum": -16000,
        +          "type": "number"
        +        }
        +      ],
        +      "type": "array"
        +    },
        +    "op": {
        +      "const": "duplicate",
        +      "type": "string"
        +    },
        +    "source": {
        +      "pattern": "^(?:\\.notdef|[a-zA-Z_][a-zA-Z0-9_.]{0,62})$",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "source"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / $defs / FilledPath
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "anyOf": [
        +        {
        +          "maximum": 16000,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "id": {
        +      "default": "outline",
        +      "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,23}$",
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "filled_path",
        +      "type": "string"
        +    },
        +    "paths": {
        +      "items": {
        +        "maxLength": 16000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "maxItems": 32,
        +      "minItems": 1,
        +      "type": "array"
        +    },
        +    "replace": {
        +      "default": false,
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "paths"
        +  ],
        +  "type": "object"
        +}
      • removedInput schema / $defs / Glyph / properties / advance / title
        Removed value: -"Advance"
      • removedInput schema / $defs / Glyph / properties / anchors / title
        Removed value: -"Anchors"
      • removedInput schema / $defs / Glyph / properties / components / title
        Removed value: -"Components"
      • removedInput schema / $defs / Glyph / properties / contours / title
        Removed value: -"Contours"
      • removedInput schema / $defs / Glyph / properties / unicodes / title
        Removed value: -"Unicodes"
      • removedInput schema / $defs / Glyph / title
        Removed value: -"Glyph"
      • removedInput schema / $defs / MovePoint / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / MovePoint / properties / point_id / title
        Removed value: -"Point Id"
      • removedInput schema / $defs / MovePoint / properties / x / title
        Removed value: -"X"
      • removedInput schema / $defs / MovePoint / properties / y / title
        Removed value: -"Y"
      • removedInput schema / $defs / MovePoint / title
        Removed value: -"MovePoint"
      • removedInput schema / $defs / Point / properties / id / title
        Removed value: -"Id"
      • removedInput schema / $defs / Point / properties / smooth / title
        Removed value: -"Smooth"
      • removedInput schema / $defs / Point / properties / type / title
        Removed value: -"Type"
      • removedInput schema / $defs / Point / properties / x / title
        Removed value: -"X"
      • removedInput schema / $defs / Point / properties / y / title
        Removed value: -"Y"
      • removedInput schema / $defs / Point / title
        Removed value: -"Point"
      • addedInput schema / $defs / Primitive
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "anyOf": [
        +        {
        +          "maximum": 16000,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "height": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 16000,
        +      "type": "number"
        +    },
        +    "id": {
        +      "default": "outline",
        +      "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,23}$",
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "primitive",
        +      "type": "string"
        +    },
        +    "replace": {
        +      "default": false,
        +      "type": "boolean"
        +    },
        +    "shape": {
        +      "enum": [
        +        "rectangle",
        +        "ellipse"
        +      ],
        +      "type": "string"
        +    },
        +    "width": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 16000,
        +      "type": "number"
        +    },
        +    "x": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    },
        +    "y": {
        +      "maximum": 16000,
        +      "minimum": -16000,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "shape",
        +    "x",
        +    "y",
        +    "width",
        +    "height"
        +  ],
        +  "type": "object"
        +}
      • removedInput schema / $defs / PutAnchor / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / PutAnchor / properties / replace / title
        Removed value: -"Replace"
      • removedInput schema / $defs / PutAnchor / title
        Removed value: -"PutAnchor"
      • removedInput schema / $defs / PutComponent / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / PutComponent / properties / replace / title
        Removed value: -"Replace"
      • removedInput schema / $defs / PutComponent / title
        Removed value: -"PutComponent"
      • removedInput schema / $defs / PutContour / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / PutContour / properties / replace / title
        Removed value: -"Replace"
      • removedInput schema / $defs / PutContour / title
        Removed value: -"PutContour"
      • removedInput schema / $defs / Remove / properties / id / title
        Removed value: -"Id"
      • removedInput schema / $defs / Remove / properties / kind / title
        Removed value: -"Kind"
      • removedInput schema / $defs / Remove / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / Remove / title
        Removed value: -"Remove"
      • removedInput schema / $defs / ReplaceGlyph / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / ReplaceGlyph / title
        Removed value: -"ReplaceGlyph"
      • removedInput schema / $defs / SetUnicodes / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / SetUnicodes / properties / unicodes / title
        Removed value: -"Unicodes"
      • removedInput schema / $defs / SetUnicodes / title
        Removed value: -"SetUnicodes"
      • addedInput schema / $defs / StrokePath
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "advance": {
        +      "anyOf": [
        +        {
        +          "maximum": 16000,
        +          "minimum": 0,
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "cap": {
        +      "default": "round",
        +      "enum": [
        +        "round",
        +        "butt",
        +        "square"
        +      ],
        +      "type": "string"
        +    },
        +    "id": {
        +      "default": "outline",
        +      "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,23}$",
        +      "type": "string"
        +    },
        +    "join": {
        +      "default": "round",
        +      "enum": [
        +        "round",
        +        "bevel",
        +        "miter"
        +      ],
        +      "type": "string"
        +    },
        +    "op": {
        +      "const": "stroke_path",
        +      "type": "string"
        +    },
        +    "paths": {
        +      "items": {
        +        "maxLength": 16000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "maxItems": 32,
        +      "minItems": 1,
        +      "type": "array"
        +    },
        +    "replace": {
        +      "default": false,
        +      "type": "boolean"
        +    },
        +    "width": {
        +      "exclusiveMinimum": 0,
        +      "maximum": 2000,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "op",
        +    "paths",
        +    "width"
        +  ],
        +  "type": "object"
        +}
      • removedInput schema / $defs / Transform / properties / contour_ids / title
        Removed value: -"Contour Ids"
      • removedInput schema / $defs / Transform / properties / matrix / title
        Removed value: -"Matrix"
      • removedInput schema / $defs / Transform / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / Transform / title
        Removed value: -"Transform"
      • removedInput schema / properties / create / title
        Removed value: -"Create"
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / expected_revision / title
        Removed value: -"Expected Revision"
      • removedInput schema / properties / glyph_id / title
        Removed value: -"Glyph Id"
      • addedInput schema / properties / master_id
        Added value: +{
        +  "default": "default",
        +  "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / operations / items / discriminator / mapping / compose_accent
        Added value: +"#/$defs/ComposeAccent"
      • addedInput schema / properties / operations / items / discriminator / mapping / duplicate
        Added value: +"#/$defs/Duplicate"
      • addedInput schema / properties / operations / items / discriminator / mapping / filled_path
        Added value: +"#/$defs/FilledPath"
      • addedInput schema / properties / operations / items / discriminator / mapping / primitive
        Added value: +"#/$defs/Primitive"
      • addedInput schema / properties / operations / items / discriminator / mapping / stroke_path
        Added value: +"#/$defs/StrokePath"
      • changedInput schema / properties / operations / items / oneOf
        Previous value: -[
        -  {
        -    "$ref": "#/$defs/PutContour"
        -  },
        -  {
        -    "$ref": "#/$defs/MovePoint"
        -  },
        -  {
        -    "$ref": "#/$defs/Transform"
        -  },
        -  {
        -    "$ref": "#/$defs/PutComponent"
        -  },
        -  {
        -    "$ref": "#/$defs/PutAnchor"
        -  },
        -  {
        -    "$ref": "#/$defs/Remove"
        -  },
        -  {
        -    "$ref": "#/$defs/SetUnicodes"
        -  },
        -  {
        -    "$ref": "#/$defs/ReplaceGlyph"
        -  }
        -]New value: +[
        +  {
        +    "$ref": "#/$defs/PutContour"
        +  },
        +  {
        +    "$ref": "#/$defs/MovePoint"
        +  },
        +  {
        +    "$ref": "#/$defs/Transform"
        +  },
        +  {
        +    "$ref": "#/$defs/PutComponent"
        +  },
        +  {
        +    "$ref": "#/$defs/PutAnchor"
        +  },
        +  {
        +    "$ref": "#/$defs/Remove"
        +  },
        +  {
        +    "$ref": "#/$defs/SetUnicodes"
        +  },
        +  {
        +    "$ref": "#/$defs/ReplaceGlyph"
        +  },
        +  {
        +    "$ref": "#/$defs/FilledPath"
        +  },
        +  {
        +    "$ref": "#/$defs/StrokePath"
        +  },
        +  {
        +    "$ref": "#/$defs/Primitive"
        +  },
        +  {
        +    "$ref": "#/$defs/Duplicate"
        +  },
        +  {
        +    "$ref": "#/$defs/ComposeAccent"
        +  }
        +]
      • removedInput schema / properties / operations / title
        Removed value: -"Operations"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / summary / title
        Removed value: -"Summary"
      • changedInput schema / required
        Previous value: -[
        -  "project_id",
        -  "expected_revision",
        -  "glyph_id",
        -  "operations"
        -]New value: +[
        +  "glyph_id",
        +  "operations",
        +  "project_id",
        +  "expected_revision"
        +]
      • removedInput schema / title
        Removed value: -"GlyphEdit"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedglyph_get15 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / glyph_id / title
        Removed value: -"Glyph Id"
      • addedInput schema / properties / master_id
        Added value: +{
        +  "default": "default",
        +  "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +  "type": "string"
        +}
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / title
        Removed value: -"GlyphGet"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedhistory_list16 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / include_total
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • removedInput schema / properties / limit / title
        Removed value: -"Limit"
      • removedInput schema / properties / offset / title
        Removed value: -"Offset"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / title
        Removed value: -"Page"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedhistory_restore14 fields changed
      • removedInput schema / properties / expected_revision / title
        Removed value: -"Expected Revision"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / summary / title
        Removed value: -"Summary"
      • removedInput schema / properties / target_revision / title
        Removed value: -"Target Revision"
      • removedInput schema / title
        Removed value: -"Restore"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedproject_create22 fields changed
      • removedInput schema / $defs / Metadata / properties / copyright / title
        Removed value: -"Copyright"
      • removedInput schema / $defs / Metadata / properties / family / title
        Removed value: -"Family"
      • removedInput schema / $defs / Metadata / properties / license_text / title
        Removed value: -"License Text"
      • removedInput schema / $defs / Metadata / properties / style / title
        Removed value: -"Style"
      • removedInput schema / $defs / Metadata / title
        Removed value: -"Metadata"
      • removedInput schema / $defs / Metrics / properties / ascender / title
        Removed value: -"Ascender"
      • removedInput schema / $defs / Metrics / properties / cap_height / title
        Removed value: -"Cap Height"
      • removedInput schema / $defs / Metrics / properties / descender / title
        Removed value: -"Descender"
      • removedInput schema / $defs / Metrics / properties / units_per_em / title
        Removed value: -"Units Per Em"
      • removedInput schema / $defs / Metrics / properties / x_height / title
        Removed value: -"X Height"
      • removedInput schema / $defs / Metrics / title
        Removed value: -"Metrics"
      • removedInput schema / properties / brief / title
        Removed value: -"Brief"
      • removedInput schema / title
        Removed value: -"ProjectCreate"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedproject_inspect16 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / include_total
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • removedInput schema / properties / limit / title
        Removed value: -"Limit"
      • removedInput schema / properties / offset / title
        Removed value: -"Offset"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / title
        Removed value: -"Page"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedproject_open11 fields changed
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / title
        Removed value: -"ProjectRef"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedproject_update30 fields changed
      • removedInput schema / $defs / Decision / properties / hypothesis / title
        Removed value: -"Hypothesis"
      • removedInput schema / $defs / Decision / properties / observation / title
        Removed value: -"Observation"
      • removedInput schema / $defs / Decision / properties / review / title
        Removed value: -"Review"
      • removedInput schema / $defs / Decision / properties / variant / title
        Removed value: -"Variant"
      • removedInput schema / $defs / Decision / title
        Removed value: -"Decision"
      • removedInput schema / $defs / Metadata / properties / copyright / title
        Removed value: -"Copyright"
      • removedInput schema / $defs / Metadata / properties / family / title
        Removed value: -"Family"
      • removedInput schema / $defs / Metadata / properties / license_text / title
        Removed value: -"License Text"
      • removedInput schema / $defs / Metadata / properties / style / title
        Removed value: -"Style"
      • removedInput schema / $defs / Metadata / title
        Removed value: -"Metadata"
      • removedInput schema / $defs / Metrics / properties / ascender / title
        Removed value: -"Ascender"
      • removedInput schema / $defs / Metrics / properties / cap_height / title
        Removed value: -"Cap Height"
      • removedInput schema / $defs / Metrics / properties / descender / title
        Removed value: -"Descender"
      • removedInput schema / $defs / Metrics / properties / units_per_em / title
        Removed value: -"Units Per Em"
      • removedInput schema / $defs / Metrics / properties / x_height / title
        Removed value: -"X Height"
      • removedInput schema / $defs / Metrics / title
        Removed value: -"Metrics"
      • removedInput schema / properties / brief / title
        Removed value: -"Brief"
      • removedInput schema / properties / expected_revision / title
        Removed value: -"Expected Revision"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / summary / title
        Removed value: -"Summary"
      • removedInput schema / title
        Removed value: -"ProjectUpdate"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedrender_glyph21 fields changed
      • removedInput schema / properties / compare_revision / title
        Removed value: -"Compare Revision"
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / glyph_id / title
        Removed value: -"Glyph Id"
      • removedInput schema / properties / guides / title
        Removed value: -"Guides"
      • removedInput schema / properties / height / title
        Removed value: -"Height"
      • addedInput schema / properties / image_mode
        Added value: +{
        +  "default": "inline",
        +  "enum": [
        +    "inline",
        +    "resource"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / master_id
        Added value: +{
        +  "default": "default",
        +  "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +  "type": "string"
        +}
      • removedInput schema / properties / points / title
        Removed value: -"Points"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / title
        Removed value: -"RenderGlyph"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedrender_text21 fields changed
      • removedInput schema / properties / compare_revision / title
        Removed value: -"Compare Revision"
      • removedInput schema / properties / dark / title
        Removed value: -"Dark"
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": "summary",
        +  "enum": [
        +    "summary",
        +    "positions",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / image_mode
        Added value: +{
        +  "default": "inline",
        +  "enum": [
        +    "inline",
        +    "resource"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / properties / kern / title
        Removed value: -"Kern"
      • addedInput schema / properties / location
        Added value: +{
        +  "maxProperties": 4,
        +  "patternProperties": {
        +    "^[A-Za-z][A-Za-z0-9]{3}$": {
        +      "maximum": 32767,
        +      "minimum": -32768,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / revision / title
        Removed value: -"Revision"
      • removedInput schema / properties / sizes / title
        Removed value: -"Sizes"
      • removedInput schema / properties / text / title
        Removed value: -"Text"
      • removedInput schema / properties / width / title
        Removed value: -"Width"
      • removedInput schema / title
        Removed value: -"RenderText"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Changedspacing_edit33 fields changed
      • removedInput schema / $defs / Bearings / properties / glyph_id / title
        Removed value: -"Glyph Id"
      • removedInput schema / $defs / Bearings / properties / left / title
        Removed value: -"Left"
      • removedInput schema / $defs / Bearings / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / Bearings / properties / right / title
        Removed value: -"Right"
      • removedInput schema / $defs / Bearings / title
        Removed value: -"Bearings"
      • removedInput schema / $defs / KernGroup / properties / glyphs / title
        Removed value: -"Glyphs"
      • removedInput schema / $defs / KernGroup / properties / name / title
        Removed value: -"Name"
      • removedInput schema / $defs / KernGroup / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / KernGroup / title
        Removed value: -"KernGroup"
      • removedInput schema / $defs / KernPair / properties / left / title
        Removed value: -"Left"
      • removedInput schema / $defs / KernPair / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / KernPair / properties / right / title
        Removed value: -"Right"
      • removedInput schema / $defs / KernPair / properties / value / title
        Removed value: -"Value"
      • removedInput schema / $defs / KernPair / title
        Removed value: -"KernPair"
      • removedInput schema / $defs / SetAdvance / properties / glyph_id / title
        Removed value: -"Glyph Id"
      • removedInput schema / $defs / SetAdvance / properties / op / title
        Removed value: -"Op"
      • removedInput schema / $defs / SetAdvance / properties / value / title
        Removed value: -"Value"
      • removedInput schema / $defs / SetAdvance / title
        Removed value: -"SetAdvance"
      • removedInput schema / properties / expected_revision / title
        Removed value: -"Expected Revision"
      • addedInput schema / properties / master_id
        Added value: +{
        +  "default": "default",
        +  "pattern": "^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,63}$",
        +  "type": "string"
        +}
      • removedInput schema / properties / operations / title
        Removed value: -"Operations"
      • removedInput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedInput schema / properties / summary / title
        Removed value: -"Summary"
      • removedInput schema / title
        Removed value: -"SpacingEdit"
      • removedOutput schema / properties / changed / title
        Removed value: -"Changed"
      • removedOutput schema / properties / data / title
        Removed value: -"Data"
      • removedOutput schema / properties / error / title
        Removed value: -"Error"
      • removedOutput schema / properties / ok / title
        Removed value: -"Ok"
      • removedOutput schema / properties / project_id / title
        Removed value: -"Project Id"
      • removedOutput schema / properties / revision / title
        Removed value: -"Revision"
      • removedOutput schema / properties / summary / title
        Removed value: -"Summary"
      • removedOutput schema / properties / warnings / title
        Removed value: -"Warnings"
      • removedOutput schema / title
        Removed value: -"Result"
    • Addedvariable_configure
  4. 13 tool updatesv0.1.0
    • First observedfont_build
    • First observedfont_validate
    • First observedglyph_edit
    • First observedglyph_get
    • First observedhistory_list
    • First observedhistory_restore
    • First observedproject_create
    • First observedproject_inspect
    • First observedproject_open
    • First observedproject_update
    • First observedrender_glyph
    • First observedrender_text
    • First observedspacing_edit

TDQS

B3.3/5.0

Scored across 20 tools

Disambiguation4/5

Most tools target distinct font-design resources and phases, such as project setup, glyph editing, rendering, validation, and history. Some boundaries blur between glyph_edit and font_edit, and among render_text, render_glyph, and render_proof, but descriptions and parameters clarify their scopes. Validation-related tools are also distinct enough across validate, analyze, and release_check phases.

Naming Consistency4/5

The set mostly follows a consistent snake_case resource_action pattern, e.g. project_create, glyph_edit, font_validate, and history_restore. Minor deviations appear in render_text, render_glyph, and render_proof, which use verb-first ordering, and in the longer font_release_check. The convention is still predictable overall.

Tool Count4/5

At 20 tools, the set is slightly above the ideal 3-15 range, but the domain is genuinely complex and spans project setup, variable configuration, editing, rendering, validation, proofing, release checks, import, build, and history. The tools do not appear redundantly padded, so the count is reasonable though heavy.

Completeness4/5

The surface covers the core font-design lifecycle: project create/open/update/inspect, variable configuration, glyph and font editing, spacing, rendering, validation/analysis, proof review, release checking, reference import, build, and history restore. Minor gaps exist, such as no explicit project listing/deletion or dedicated glyph deletion/export operation, but agents have workarounds and the critical paths are present.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to diagnose, modify, and validate OTF/TTF fonts interactively through a set of read-only, write, and validation tools.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to interact with FontLab for font design and manipulation, including querying font metadata, creating/modifying glyphs, applying transformations, and exporting fonts.
    8
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP bridge for AI-assisted type design in GlyphsApp. Lets Claude, Cursor, or any MCP client read and write font data directly in GlyphsApp — bidirectional, real-time, live in the editor.
    7
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI tools to create and edit Font Proof documents for type designers, supporting PDF font proofs and live-reload from Glyphs.app.
    15 npm
    MIT