Skip to main content
Glama
Hbler

parti-mcp

by Hbler

parti-mcp v2

An MCP server that renders architectural floor plans and site plans as SVG in a blueprint aesthetic, following real architectural drawing conventions. Built with precision planar geometry (Clipper WASM + flatten-js).

Office floor plan (office.json)

Residential floor plan (house.json)

Office building Level 2 — elevator/stair core, corridor, offices, columns

Two-bedroom bungalow — living/dining, kitchen, hall, bedrooms, bathroom

Both images are rendered directly by the server from the specs in examples/ — walls with cut poché, door swing symbols, room labels with computed areas, an elevator shaft and stair with UP/DN, dimensions, a title block, north arrow, and scale bar.

Features

  • Precision geometry engine: Uses Clipper (js-angusj-clipper) for robust planar geometry operations with integer-precision scaling

  • Analytical primitives: flatten-js for centroids, point-along-path, perpendiculars, and arc geometry

  • Architectural rendering: Proper wall junctions (offset→union→cut→stroke), door/window symbols, room labels with area calculations

  • Vertical circulation & structure: Stairs (tread lines + UP/DN arrow + break line), ladders, elevators (shaft symbol), columns/piers with material poché

  • Wall vocabulary: Straight or circular-arc (curved) walls, full-height or low (half/pony/knee) walls, and mixed materials on a single floor (rendered per material group)

  • Legible labels: Room and site labels render on a background "safe area" halo so busy hatching never bleeds through the text

  • Multi-theme output: Blueprint (dark) and Whiteprint (light) themes with theme-aware text contrast

  • Multi-scale support: Automatic scaling from paper millimeters to model units (1:100, 1:50, 1:200, etc.)

  • Multi-floor plans: Render each floor separately or batch process buildings

  • Site and city plans: Buildings, parcels, roads, green spaces, water features, barriers, trees, and paved areas

Related MCP server: Atelier

Architecture

Core Geometry Pipeline

  1. Input: FloorPlanSpec or SiteSpec (Zod-validated schemas)

  2. Geometry Processing:

    • Wall/road polylines are offset to solid bands (Clipper)

    • Overlapping bands are unioned (Clipper with NonZero fill rule)

    • Junctions are cleaned via offset→union→cut workflow

    • Interior polygons (rooms/parcels) are extracted

  3. Rendering:

    • Walls/roads/outlines rendered as stroked paths (no fill)

    • Rooms/buildings rendered as filled polygons with hatch patterns

    • Openings (doors/windows) cut from walls or drawn as symbols

    • Text labels positioned at centroids with automatic contrast detection

    • Title blocks, scale bars, and north arrows added per AIA conventions

  4. Output: SVG with embedded patterns, markers, and defs

Key Files

  • src/geometry/clipper.ts: Clipper WASM wrapper, offset, union, difference operations

  • src/geometry/primitives.ts: flatten-js wrappers for centroids, perpendiculars, point-along-path, polygon area

  • src/geometry/scale.ts: paper-mm ↔ model-unit conversion, dimension text formatting, scale-bar tick stops

  • src/render/theme.ts: blueprint/whiteprint palettes, lineweight/linetype resolution, contrast-aware text color

  • src/render/titleblock.ts: Title block generation with scaled text and backgrounds

  • src/render/symbols.ts: Door swing, window glazing, grid bubbles, dimension strings, scale bars, north arrows

  • src/render/sheet.ts: Sheet assembly — border, title block, north arrow, scale bar around the drawing content

  • src/tools/renderFloorPlan.ts: Floor plan rendering pipeline

  • src/tools/renderSitePlan.ts: Site plan rendering pipeline

Getting Started

Use it as an MCP server

parti-mcp is a stdio MCP server: an MCP client (Kiro, Claude Desktop, etc.) launches it and calls its tools. You don't run it by hand — you point your client's config at a command that starts it.

Run directly from GitHub (no clone, no install step):

{
  "mcpServers": {
    "parti-mcp": {
      "command": "npx",
      "args": ["-y", "github:Hbler/parti-mcp"]
    }
  }
}

Or, once published to npm:

{
  "mcpServers": {
    "parti-mcp": {
      "command": "npx",
      "args": ["-y", "parti-mcp"]
    }
  }
}

Either way the client spawns the server, which exposes three tools: render_floor_plan, render_site_plan, and ping. The server advertises the full JSON Schema for each spec plus a usage brief in its MCP initialize response, so the calling model knows every field.

The package builds itself on install (a prepare step compiles TypeScript to dist/), and the compiled entry runs on plain Node — no global tsx needed on the consumer's machine.

Develop from source

git clone https://github.com/Hbler/parti-mcp
cd parti-mcp
npm install          # also builds dist/ via the prepare step
npm start            # run the server over stdio from TypeScript source (tsx)
npm run build        # type-check and emit dist/

To point an MCP client at your working copy instead of the published package:

{
  "mcpServers": {
    "parti-mcp": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/parti-mcp/src/index.ts"]
    }
  }
}

Running Tests

npm test

Covers:

  • Geometry operations (clipping, offsetting, unions)

  • Schema validation

  • Rendering pipeline

  • Integration tests with real examples

  • Regression tests for known bugs (junction seams, text sizing, enclosed-room poché, road gap-bridging)

Verifying output

Two layers, because structural checks alone miss geometry bugs:

Structural (automated). Render every example through the real tool handlers and confirm each produces well-formed SVG:

npm run verify

This catches broken or stale examples and render errors. It does not judge appearance.

Appearance (rasterize and look). The definitive check is to turn the SVG into an image and look at it — inspecting raw coordinates reliably misses real defects (a flooded room, a road block bridging a gap and hiding what's beneath, overlapping labels). Render the SVG, rasterize it, and open the result:

# macOS (built in, no install):
qlmanage -t -s 1600 -o out/ plan.svg

# Linux / CI alternatives:
rsvg-convert plan.svg -o plan.png      # librsvg
resvg plan.svg plan.png                # resvg
# or load the SVG in headless Chrome and screenshot it

Then confirm the things automation can't: line-weight hierarchy reads, poché/hatch fills walls (rooms are not flooded), doors swing and windows glaze within the wall, dimensions are legible, and — for site plans — roads merge at junctions while gaps between road spurs stay open with nothing hidden under a filled block.

Rasterization is intentionally not built into the server: the tools emit SVG only. Keeping raster out keeps the server a pure, deterministic renderer with a clean npx install (no native image dependency), so "look at a PNG" is a downstream verification step, as above.

Rendering examples without a client

To render the bundled examples directly (writes SVGs to smoke-output/):

node --import=tsx scripts/smoke-test.mjs

Or call a tool handler from your own script. Import the .ts sources with tsx when running from a source checkout, or the built dist/*.js when running against a compiled install:

import { initializeClipper } from "./src/geometry/clipper.ts";
import { handleRenderFloorPlan } from "./src/tools/renderFloorPlan.ts";
import fs from "node:fs";

await initializeClipper(); // required once before any render
const spec = JSON.parse(fs.readFileSync("examples/house.json", "utf-8"));
const result = await handleRenderFloorPlan({ spec });
console.log(result.content[0].text); // SVG output (one entry per floor)

Example Specifications

Floor Plan (house.json)

Single-floor residential plan:

  • 15m × 10m footprint

  • 2 rooms (living room, kitchen)

  • Interior partition wall

  • Exterior doors/windows

  • Dimension annotations

{
  "unit": "m",
  "scale": "1:50",
  "theme": "blueprint",
  "titleBlock": { /* ... */ },
  "floors": [
    {
      "id": "ground-floor",
      "level": 0,
      "outline": [[0, 0], [15, 0], [15, 10], [0, 10]],
      "walls": [ /* paths with thickness */ ],
      "rooms": [ /* polygons with labels */ ],
      "openings": [ /* doors and windows */ ],
      "dimensions": [ /* annotation lines */ ]
    }
  ]
}

Multi-Floor (two-floor.json)

Two-story residential:

  • Ground floor: Living Room, Kitchen/Dining, Entry Hall, WC

  • First floor: bedrooms, bathroom, landing

  • A stacked stair (UP on the ground floor, DN on the first) positioned clear of door swings

  • Columns placed on the structural grid

  • Interior partitions on both levels

Detailed House (house-detailed.json)

Exercises the fuller vocabulary: a low (knee) wall, stairs running to an upper level, and a loft-access ladder.

Curved Wall (curved-wall.json)

Minimal demo of a curved wall (a shallow bay window authored as a two-point wall with curve) and a round column.

Office Building — Level 2 (office.json)

Commercial floor plate: an elevator + stair core (single lobby, one corridor door), a central corridor, two restrooms opening onto the corridor, open-plan and cellular offices, and columns on grid.

City / Figure-Ground (city.json)

Urban site plan at 1:500: labeled building footprints, a street grid, and a park plaza.

Whiteprint (house-whiteprint.json)

The bungalow rendered in the light (whiteprint) theme, with one highlighted room demonstrating per-element style.fill.

Site Plan (site-plan.json)

Residential site with:

  • Main building footprint

  • Property parcel boundary

  • Street frontage

  • Driveway (asphalt)

  • Sidewalk (concrete)

  • Pool (water feature)

  • Landscaping (lawn, garden)

  • Property fence

  • Site trees with species

{
  "unit": "m",
  "scale": "1:100",
  "buildings": [ /* footprints with labels */ ],
  "roads": [ /* paths with width */ ],
  "pavedAreas": [ /* polygons with surface type */ ],
  "greenSpaces": [ /* polygons with landscape type */ ],
  "water": [ /* polygons with water type */ ],
  "barriers": [ /* paths with barrier type */ ],
  "trees": [ /* positions with radius and species */ ]
}

CLI Tools

renderFloorPlan

Renders architectural floor plans with proper junction handling and legend.

export async function handleRenderFloorPlan(input: {
  spec: FloorPlanSpec;
  outputPath?: string;
}): Promise<ToolResult>;

Input Schema (FloorPlanSpec):

  • unit: "m" | "ft" | "mm"

  • scale: "1:50" | "1:100" | "1:200" (etc.)

  • theme: "blueprint" | "whiteprint"

  • titleBlock: Optional title block metadata

  • floors[]: Array of floor specs, each with:

    • outline: Boundary polygon

    • walls[]: Wall centerlines with thickness and optional material (mixed materials on one floor render per group). Optional heightClass: "full" (default, solid cut poché) or "low" (half/pony/knee wall or railing below the cut plane → dashed outline, no fill). A wall may curve: give a two-point path plus curve: { radius, clockwise } and the server tessellates a circular arc that unions/cuts like a straight wall.

    • rooms[]: Room polygons with type, optional custom fill, optional label (name; area is still appended) and labelOrientation (horizontal | vertical). Labels render on a legibility halo

    • openings[]: Doors/windows referencing a wall by wallId at positionAlongWall in [0,1]; doors need hinge (start|end) + swingSide (left|right)

    • stairs[]: Straight-run stairs — footprint, run [bottom, top] travel centerline, treads count, direction (up|down)

    • ladders[]: path [start, end] + width (rails + rungs)

    • elevators[]: footprint (shaft rectangle) + optional label (X-in-box shaft with inset car)

    • columns[]: position, shape (square|rectangular|round), size or width+depth, optional material (poché footprint — place on grid intersections)

    • dimensions[]: Annotation lines with text

    • grid: Optional structural grid (labeled bubbles)

Output: SVG at outputPath or returned as text

renderSitePlan

Renders site plans with buildings, roads, landscape, and utilities.

export async function handleRenderSitePlan(input: {
  spec: SiteSpec;
  outputPath?: string;
}): Promise<ToolResult>;

Input Schema (SiteSpec):

  • buildings[]: Building footprints with label and optional labelOrientation (horizontal | vertical). Optional footprintCurves[] curves the footprint: an edge bow { edge, radius, clockwise } (a curved facade) or a corner round { corner, setbackIn?, setbackOut?, radius?, clockwise? } (a rounded/filleted corner — give a radius for a tangent fillet, or setbackIn/setbackOut for a free arc; a "rounded square" is four corner entries)

  • roads[]: Road polylines with width; optional curve: { radius, clockwise } on a two-point path renders a curved carriageway. A roundabout is a composition: a closed ring of curved-road segments (e.g. four quarter-arcs chained around a circle) forms an open annular carriageway, with a center island drawn as a green/paved circle

  • pavedAreas[]: Paved polygons (driveways, parking, sidewalks, patios, decks). Optional elevated: true renders the area above water (for a deck/boardwalk/jetty over a pond or pool); optional label overrides the surface-derived name, labelOrientation rotates it

  • greenSpaces[]: Landscape polygons (lawn, garden, trees); optional label/labelOrientation

  • water[]: Water features (pools, ponds); optional label/labelOrientation

  • barriers[]: Fences, walls, hedges

  • trees[]: Individual tree positions with radius and species

Labels: on area entities (buildings, rooms, paved areas, water, green spaces), label overrides the auto-derived name (a room still appends its computed area); labelOrientation: "vertical" rotates the label 90° (reading bottom-to-top) so it fits a narrow shape; labelPosition places the label within the area — center (default) or one of eight bounding-box positions (top-left, top, top-right, left, right, bottom-left, bottom, bottom-right). Corner positions anchor the text to the corner, reading inward.

Scale and Units

All coordinates are in model units (meters, feet, mm depending on spec).

Scale conversion is automatic:

  • Input scale string (e.g., "1:100") is parsed

  • SVG font sizes and line widths are scaled appropriately

  • At 1:100 with meters, 0.1 model units = 1cm on paper

  • Text is rendered proportional to drawing size (0.5–3% of bbox height)

Unit handling:

  • All internal calculations use model units

  • Title blocks, scale bars adapt to unit and scale

Theme System

Blueprint (default)

  • Background: Prussian blue (#0B3D91)

  • Ink: Pale cyan (#E0F2FF)

  • Poché fill: Darker blue (#1A4BA8)

Whiteprint (opt-in)

  • Background: White (#FFFFFF)

  • Ink: Black (#000000)

  • Poché fill: Light gray (#D3D3D3)

Per-element fill and label contrast

Any drawable entity may set style.fill to highlight it in a specific color, regardless of theme. Room and site labels render on a background "safe area" halo (a card behind the text) so that dense floor/site hatching never renders through the label. On top of the halo, getContrastingTextColor picks whichever of the theme's ink or background color has the greater luminance distance from the room's actual fill, so a label stays legible whether the room uses the theme default or a custom highlight color, in either theme.

Technical Details

Geometry Operations

Offsetting Walls to Bands:

Path (centerline) + thickness → Solid band polygon

Junction Handling (offset→union→cut→stroke), the core fix that makes connected walls/roads read as one drawing instead of overlapping outlines:

1. Offset every wall/road centerline in a floor/site to its own solid band (OpenButt end type)
2. Union all bands into one merged polygon (NonZero fill rule — EvenOdd would
   treat the genuinely-overlapping area at a junction as a hole and split
   the result back into separate pieces)
3. Difference the door/window opening cutters from that merged polygon
4. Stroke the single resulting boundary once — never per-wall

Walls are grouped by material and each group runs through this pipeline independently, so a floor can mix materials (each hatched on its own). Each group's cut poché is emitted as a single fill-rule="evenodd" path: when interior walls form a connected loop, the union returns the enclosed room void as a separate opposite-winding subpath, and even-odd makes that void a hole rather than a filled polygon — otherwise the room interior would be flooded with the wall hatch.

Rooms are author-supplied, not derived. A Room.polygon is authored directly in the spec to the room's interior wall face — it is not extracted or computed from the wall geometry. This keeps the computed area (getPolygonArea) honest as usable floor area, and means room fill always meets wall poché with no gap as long as the spec author places the room polygon at the wall's inner face. Label position is the room polygon's centroid (getCentroid).

Text Rendering

All text sizing is computed as:

fontSize (model units) = textSizeInPaperMm * modelPerPaperMm(scale, unit)
modelPerPaperMm = scaleDenominator / mmPerUnit

For scale "1:100" with unit "m" (1 m = 1000 mm):

  • modelPerPaperMm = 100 / 1000 = 0.1

  • 1.5mm text → 1.5 * 0.1 = 0.15 model units (15 cm — reads correctly on a drawing sized in metres at 1:100)

This same conversion drives every line weight, tick size, and bubble radius — nothing is a hardcoded pixel/model-unit constant, so output reads correctly whether the spec is a metre-scale floor plan or a much larger site plan.

Text is rendered with font-family="monospace" for deterministic sizing.

Patterns and Hatches

Hatches are defined as SVG <pattern> elements (patternUnits="userSpaceOnUse", so density stays scale-correct and continuous across adjacent shapes) in <defs> and referenced via fill="url(#hatch-type)":

  • hatch-brick: 45° diagonal lines

  • hatch-masonry: 45° diagonal lines, coarser than brick

  • hatch-concrete: Stipple/dot pattern

  • hatch-insulation: Batting pattern

  • hatch-wood: Parallel plank lines (backs the wood material and deck surface)

  • hatch-lawn: Scattered circles for grass

  • hatch-pavers: Grid pattern for paved areas

  • hatch-earth: Dense 45° lines for soil

Known Limitations

  • All polylines are treated as open paths; closed loops require explicit endpoint

  • Text is positioned at geometric center; complex labels may benefit from manual adjustment

  • Curved walls are supported as circular arcs only (a two-point path plus curve: { radius, clockwise }, tessellated before offsetting); non-circular curves (splines, ellipses) are not supported

  • Plans are a single 2D horizontal cut — there is no continuous vertical model. Furniture/fixtures and MEP are out of scope

  • High-precision geometry relies on integer arithmetic; very large drawings may lose precision

Contributing

All code follows TypeScript strict mode. Changes must:

  1. Pass npm run build (TypeScript check)

  2. Pass npm test (full test suite)

  3. Update relevant tests if schemas or rendering change

  4. For new examples, render to output/examples/ and visually verify (e.g. rasterize with qlmanage -t -s 1600 -o <dir> output/examples/*.svg)

License

MIT — see LICENSE.

Version History

v2 is a full rebuild of an earlier Turf.js-based prototype: a different geometry engine (Clipper + flatten-js, replacing Turf's geospatial/spherical math, which was the root cause of a geometry bug at wall/road junctions) and a renderer that follows real architectural drawing conventions (blueprint aesthetic, real units + named scale, line-weight hierarchy, poché/material hatching, dimensioning, structural grid, title block, north arrow, scale bar) rather than a generic vector diagram. See docs/REASONS-CANVAS.md for the full design history.

Available Tools

3 tools
pingA

Responds with pong

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description is the only behavioral disclosure. Responds with pong is a complete observable behavior for a zero-parameter tool, and the absence of side effects is implied by the trivial nature of the operation. An explicit safety statement would have made it fully transparent.

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 short sentence with no wasted words. It is immediately readable and every word contributes to the meaning.

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

Completeness5/5

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

Given the lack of parameters, lack of side-effecting inputs, and limited response, the description fully communicates what the agent needs to invoke and interpret the tool correctly. There are no missing requirements.

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

Parameters4/5

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

The tool has no parameters, so the input schema already covers everything. The description does not need to add parameter information, and it does not.

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 outcome: respond with pong. It makes the tool recognizable as a liveness check and distinguishable from the rendering siblings, though it does not explicitly name those siblings or state what it is not.

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 usage guidance is provided. When to use this tool versus the render tools is inferable from the name and the convention of ping, but the description itself does not state when it should be chosen.

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

render_floor_planA

Renders an interior floor plan (floors, rooms, walls, door/window openings, dimensions, structural grid) from a FloorPlanSpec. Returns one SVG per floor. See the server instructions for conventions and the coherence contract.

ParametersJSON Schema
NameRequiredDescriptionDefault
specYesFloorPlanSpec object (or JSON string) defining the floor plan. See this schema's properties for every field.
outputPathNoOptional file path to write the SVG (relative to the server's allowed output/ directory). If omitted, the SVG is returned as tool content only.

TDQS

A3.9/5.0
Behavior3/5

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

No annotations are provided, so the description carries most of the behavioral disclosure burden. It does disclose the main output behavior—'Returns one SVG per floor'—and points to server instructions for conventions and the coherence contract. However, it does not surface the outputPath side effect (writing a file) or validation/error behavior, so transparency is adequate but incomplete.

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 the main action and return behavior front-loaded. It includes a useful compact list of rendered elements and adds a pointer to conventions without unnecessary fluff. Every sentence earns its place.

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?

The tool consumes a deeply nested FloorPlanSpec, has no output schema, and relies on a short description plus 'server instructions' for important behavior. It covers the obvious use case and return shape, but an agent still may not know what happens when outputPath is set or where the coherence contract is defined. The definition is minimally viable but leaves dependency on external context.

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 input schema already documents both parameters well, including that spec is a FloorPlanSpec object or JSON string and that outputPath controls file writing versus in-content return. Schema description coverage is 100%, so the description adds no meaningful parameter semantics beyond naming FloorPlanSpec. Baseline 3 is appropriate.

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 names a concrete action and resource: it 'Renders an interior floor plan' from a FloorPlanSpec, and enumerates what is included (floors, rooms, walls, door/window openings, dimensions, structural grid). It also states the return shape: 'Returns one SVG per floor'. The 'interior' qualifier clearly separates it from the sibling tool render_site_plan.

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?

The description makes the use case clear: use it when you have a FloorPlanSpec and need interior floor plan renderings. It stops short of explicitly naming render_site_plan as the alternative or listing when-not-to-use cases, but 'interior' plus the sibling tool name supplies the boundary. This is clear context with only a minor lack of explicit exclusions.

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

render_site_planA

Renders an exterior site plan (buildings, parcels, roads, hardscape, water, landscape, barriers, trees) from a SiteSpec. Returns one SVG. See the server instructions for conventions and the coherence contract.

ParametersJSON Schema
NameRequiredDescriptionDefault
specYesSiteSpec object (or JSON string) defining the site plan. See this schema's properties for every field.
outputPathNoOptional file path to write the SVG (relative to the server's allowed output/ directory). If omitted, the SVG is returned as tool content only.

TDQS

A4/5.0
Behavior3/5

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

With no annotations provided, the description carries the full behavioral burden: it does state that the tool returns one SVG and points to the server instructions for conventions and coherence contract. However, it does not disclose side effects or permissions — e.g., whether writing via outputPath is signed, whether the operation is purely non-destructive, or what happens on invalid input/coherence contract violations.

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 sentences with no filler: the first packs verb, scope of the plan, and the input; the second states the output format and directs to the authoritative conventions. The categories listed are concrete and useful, and the pointer to server instructions keeps the text from bloating.

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 tool with an extensive nested schema, the description plus the richly documented parameter schemas give an agent what it needs to invoke correctly: expected input domain, output shape, the optional file write behavior, and the path to the required conventions/coherence rules. Return-value semantics are reasonably covered by 'single SVG', though there could be marginally more context about acceptance/validation behavior when a spec is malformed.

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 100%; the schema already explains both spec and outputPath in detail, including that spec can be SiteSpec object or JSON string and that outputPath is optional. The tool description adds little parameter-level insight beyond reiterating the SiteSpec input and SVG output, so the baseline 3 applies.

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 ('Renders') with a specific resource ('exterior site plan'), enumerates the content types (buildings, parcels, roads, hardscape, water, landscape, barriers, trees), names the input form (SiteSpec), and states the exact output ('one SVG'). The explicit 'exterior' qualifier differentiates it from the sibling render_floor_plan without needing to open either schema.

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?

The description gives clear context: exterior site plans from a SiteSpec, and the sibling-tool name render_floor_plan makes the alternative obvious. It does not explicitly state 'for interior layouts, use render_floor_plan' or list exclusion conditions, so it rises to 'clear context, no exclusions' but not to the explicit when-to-use/when-not-to-use level of a 5. The pointer to server instructions also guides the agent on where to read expected conventions.

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. 1 tool updatev1.2.0
    • Changedrender_site_plan2 fields changed
      • addedInput schema / properties / spec / properties / buildings / items / properties / footprintCurves
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "clockwise": {
        +        "type": "boolean"
        +      },
        +      "corner": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "edge": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "radius": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "setbackIn": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "setbackOut": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / spec / properties / roads / items / properties / curve
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "clockwise": {
        +      "default": false,
        +      "type": "boolean"
        +    },
        +    "radius": {
        +      "exclusiveMinimum": 0,
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "radius",
        +    "clockwise"
        +  ],
        +  "type": "object"
        +}
  2. 2 tool updatesv1.1.1
    • Changedrender_floor_plan2 fields changed
      • addedInput schema / properties / spec / properties / floors / items / properties / rooms / items / properties / labelOrientation
        Added value: +{
        +  "enum": [
        +    "horizontal",
        +    "vertical"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / floors / items / properties / rooms / items / properties / labelPosition
        Added value: +{
        +  "enum": [
        +    "center",
        +    "top-left",
        +    "top",
        +    "top-right",
        +    "left",
        +    "right",
        +    "bottom-left",
        +    "bottom",
        +    "bottom-right"
        +  ],
        +  "type": "string"
        +}
    • Changedrender_site_plan12 fields changed
      • addedInput schema / properties / spec / properties / buildings / items / properties / labelOrientation
        Added value: +{
        +  "enum": [
        +    "horizontal",
        +    "vertical"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / buildings / items / properties / labelPosition
        Added value: +{
        +  "enum": [
        +    "center",
        +    "top-left",
        +    "top",
        +    "top-right",
        +    "left",
        +    "right",
        +    "bottom-left",
        +    "bottom",
        +    "bottom-right"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / greenSpaces / items / properties / label
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / greenSpaces / items / properties / labelOrientation
        Added value: +{
        +  "enum": [
        +    "horizontal",
        +    "vertical"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / greenSpaces / items / properties / labelPosition
        Added value: +{
        +  "enum": [
        +    "center",
        +    "top-left",
        +    "top",
        +    "top-right",
        +    "left",
        +    "right",
        +    "bottom-left",
        +    "bottom",
        +    "bottom-right"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / pavedAreas / items / properties / elevated
        Added value: +{
        +  "type": "boolean"
        +}
      • addedInput schema / properties / spec / properties / pavedAreas / items / properties / label
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / pavedAreas / items / properties / labelOrientation
        Added value: +{
        +  "enum": [
        +    "horizontal",
        +    "vertical"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / pavedAreas / items / properties / labelPosition
        Added value: +{
        +  "enum": [
        +    "center",
        +    "top-left",
        +    "top",
        +    "top-right",
        +    "left",
        +    "right",
        +    "bottom-left",
        +    "bottom",
        +    "bottom-right"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / water / items / properties / label
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / water / items / properties / labelOrientation
        Added value: +{
        +  "enum": [
        +    "horizontal",
        +    "vertical"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / spec / properties / water / items / properties / labelPosition
        Added value: +{
        +  "enum": [
        +    "center",
        +    "top-left",
        +    "top",
        +    "top-right",
        +    "left",
        +    "right",
        +    "bottom-left",
        +    "bottom",
        +    "bottom-right"
        +  ],
        +  "type": "string"
        +}
  3. 3 tool updatesv1.0.0
    • First observedping
    • First observedrender_floor_plan
    • First observedrender_site_plan

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: ping is a liveness check, render_site_plan handles exterior/environmental layouts, and render_floor_plan handles interior layouts. There is no realistic ambiguity between the render tools because their domains are mutually exclusive.

Naming Consistency4/5

The two primary tools follow a consistent render_<plan_type> naming convention, which is clear and predictable. ping is a minor deviation, but it is standard enough for a health-check tool and does not harm readability.

Tool Count4/5

With just three tools, the server is minimal but still well-scoped for a focused rendering server: a health check plus two specialized actions. It slightly sits at the low end, but every tool has a distinct reason to exist.

Completeness4/5

The server covers both core domains it advertises—exterior site plans and interior floor plans—with no obvious dead ends. A section/elevation render or spec-related utility could extend it, but for the stated render-focused purpose the set is reasonably complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables to create, compose, and export SVG documents programmatically using the svgwrite library through tool calls. Supports shapes, groups, gradients, and pattern generators.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Converts spoken descriptions into standards-compliant floor plans and furnished 3D models, enabling real-time collaborative editing through a live browser editor with Claude AI.
    34
    Apache 2.0
  • F
    license
    A
    quality
    B
    maintenance
    An MCP server that generates standalone SVG architecture diagrams from text descriptions, running entirely on your machine with no dependencies or network access.
    8
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides 3D architecture visualization from floorplan layouts, with tools for generating 3D models, rendering perspectives, and exporting models. Currently uses a stub provider with placeholder URLs.
    -