Skip to content

Render layer-filtered SVGs

render_svg turns a DXF layout into an SVG file, filtered to layers matching a pattern. It’s the fastest way to see what a layer inventory or parcel extraction is talking about.

{
"tool": "render_svg",
"operation": {
"file_path": "/data/site-plan.dxf",
"operation": "render",
"parameters": {
"layer_pattern": "C-PROP*",
"output_name": "property-lines",
"layout": "Model"
}
}
}

The file is written to the server’s output directory as property-lines.svg, and the response reports the path, file size, entity count, and SVG element count. output_name must be a bare filename stem — path separators are rejected.

layout accepts "Model" (default) or any paperspace sheet name from list_sheets, so you can render a specific deliverable sheet.

A path inside the server’s container is useless to a caller talking HTTP, so every render is returned three ways:

  • svg — the markup itself, inline in the response, when the file is at or under 256 KB (RENDER_INLINE_MAX_BYTES). Force it either way with return_content: true / false.
  • url — https://your-domain/renders/property-lines.svg, served straight from the output directory. Present when RENDER_BASE_URL or PUBLIC_DOMAIN is configured; omitted otherwise, because a localhost URL a remote caller can’t reach is worse than no URL.
  • resource_uri — render://property-lines.svg, readable through MCP’s resources/read for clients that can’t fetch HTTP.

output_size_bytes is always reported, and when the markup is left out content_note says exactly why. Both retrieval paths serve plain *.svg files living directly in the output directory: traversal, separators, symlinks pointing elsewhere, and non-SVG suffixes all get a 404.

Hatches, not coordinates, are what blow up file size

Section titled “Hatches, not coordinates, are what blow up file size”

The default hatch_policy is "outline". On a civil drainage layer with 24 entities — two of them GRASS-pattern hatches — the same drawing renders to:

hatch_policy Output
"outline" (default) 9.9 KB
"solid" 10 KB
"ignore" 4.8 KB
"full" ~8 MB

(The "full" figure drifts between runs — ezdxf bounds its pattern renderer with a timeout.) Pattern hatch lines are individual vectors, and a fine pattern over a large area is millions of them. render_svg is a look at it tool, so it draws hatch boundaries by default; pass "full" when the fill pattern itself is the point, and expect the megabytes.

coordinate_space (default 1000000) trims digits off every coordinate and buys maybe 40% on a vector-heavy file. It’s a real knob, but it is not the fix for a huge render — hatch_policy is.

extents: [min_x, min_y, max_x, max_y] takes modelspace coordinates and crops everything outside the window away — the cheap alternative to resolving a paperspace viewport. Take the numbers from a prior render’s bounds or from survey_dxf_layers, then narrow.

stroke_color (a hex color) overrides every entity color, stroke_width sets one width in millimetres for the whole drawing, and background takes "transparent" (default), "white", "black", or a hex color.

Transparent means no background rect at all, not a zero-opacity one. Some rasterizers composite a zero-opacity white rect as opaque black, which is how a “transparent” SVG turns up as a black square in a PNG. There’s nothing left to composite.

Here’s the trap that motivates this page: DXF renderers normally skip entities on frozen or off layers, faithfully reproducing what a plotter would show. On real civil files, that hides exactly the layers worth looking at — no-plot boundary layers (*-NPLT suffixes) are routinely frozen precisely because they’re working linework, not deliverable graphics.

mcdrafter takes a position: if you name a layer pattern, you mean it. Frozen and off layers that match the pattern are forced visible before rendering. You asked to see the property boundaries; you get the property boundaries, plot flags notwithstanding.

If you want plot-faithful output, render with a broad pattern against a paperspace sheet — the layout’s own viewport conventions carry most of that intent.

A pattern that matches no layers returns an error that includes similar layer names as a hint:

{
"error": "No entities on layers matching 'C-PROP-ESMT-LINE' in layout 'Model' - nothing to render",
"similar_layer_names": ["C-PROP-ESMT-LINE", "XREF-PLAN$0$C-PROP-ESMT-LINE"]
}

The hint is a substring scan of the layer table, so a layer that exists but carries no geometry still points you at its xref-bound twin.

You never get a silently empty SVG to puzzle over.

Layer filtering applies to top-level entities in the layout. An INSERT (block reference) passes the filter when its own layer matches, and then renders its complete block content — sub-entities inside the block are not individually filtered. This is deliberate: block content drawn on layer 0 legitimately inherits the insert’s layer, and filtering inside blocks would drop valid geometry.

Practical consequence: if a matched layer contains block references, expect their full symbols in the output, not just the fragments that share the layer name.

Rendering a full sheet of a large civil file (tens of thousands of entities) takes on the order of 10 seconds, most of it parsing the DXF. Prefer narrow layer patterns — they’re faster, smaller, and more legible. The typical loop is: survey to find a layer, render just that layer, widen only if the picture is missing context. When output is still large, reach for extents before widening the pattern.