Escape

@quario/mcp

An MCP server that exposes quario as two tools. It runs locally over stdio, and npx @quario/mcp starts it. The package carries the engine and the five render targets as dependencies, and needs Node 22 or later.

Configuration

The server reads its configuration from environment variables. There are no flags and no config file. An empty variable counts as unset.

Variable Sets When unset
QUARIO_LICENSE the license key unlicensed, and the output carries the watermark
QUARIO_LOCALE the default locale en-US
QUARIO_CURRENCY the default currency none
QUARIO_TIME_ZONE the default timeZone UTC
QUARIO_SCHEMES the href schemes, comma-separated https:,mailto:
QUARIO_MAX_DEPTH a query budget, or Infinity 500
QUARIO_MAX_NODES a query budget, or Infinity unbounded
QUARIO_MAX_RESULTS a query budget, or Infinity unbounded
QUARIO_DATA_ROOT the directory dataPath and $image resolve in CLAUDE_PROJECT_DIR, else dataPath fails
QUARIO_OUT_DIR the directory the server writes to quario-mcp under the system temp directory

A value the server can’t run with stops it at startup, and the message goes to stderr. That covers a budget that doesn’t parse and a scheme the engine refuses. It also covers a data root that doesn’t exist, and an output directory the server can’t create or write. A license key that fails verification is the one exception. The server starts, and the output carries the watermark.

validate_report

Reads a definition for problems without rendering it.

Field Type Notes
definition object Required.
targets array of "html", "pdf", "xlsx", "docx", "csv" Optional. Checks required against each target.

The definition field carries the full JSON Schema of the report document, descriptions included. The server reads the call against that schema and passes the definition to the engine unchecked. A fault comes back as one problem at the path it sits at.

A problem is a successful result, never an error. The result carries structuredContent with { problems, warnings }, and one text block holding the same object as JSON.

result
type Problem = {
  path: string
  source?: string
  message: string
  code?: string
  start?: number
  end?: number
}

type Warning = { path: string; message: string }

code, start and end come from the located diagnostic when the engine has one.

render_report

Renders a definition to one target and writes the output to a file.

Field Type Notes
definition object Required.
target "html", "pdf", "xlsx", "docx" or "csv" Required.
data any JSON value Give exactly one of data and dataPath.
dataPath string A JSON file inside the data root.
params object Optional. Values for the definition’s params.
locale string Optional. Overrides QUARIO_LOCALE for this call.
currency string Optional. Overrides QUARIO_CURRENCY for this call.
timeZone string Optional. Overrides QUARIO_TIME_ZONE for this call.
filename string Optional. A file name without a directory.
options object Optional. page, meta, and filter for xlsx.

The tool plans the definition against its target, so a required declaration that target loses is a problem. A definition with problems returns the same { problems, warnings } as validate_report, marked isError.

options passes to the target factory. The server refuses fonts and paths, and an unknown key returns the factory’s own message as an error. The csv target takes no options.

Render data. Give exactly one of data and dataPath. dataPath resolves inside the data root, tested after symlinks resolve, and without a data root the server refuses it. A file that doesn’t parse returns the server’s own message, never the file’s text. An image arrives as { "$image": "<path>" } or { "$base64": "…" }, and either decodes to bytes before the render at any depth. An $image path resolves inside the data root, inside a dataPath file too, and names a PNG or JPEG. Without a data root the server refuses it, and a refusal names its place in the data, such as $.input.logo.

The output file. Every target writes a file to QUARIO_OUT_DIR and returns its location, never its content. filename holds no separator and isn’t .., and the server forces the target’s extension. Without one the name is report-<timestamp>.<ext>. The server never overwrites: a name that exists gets -1, then -2.

result
type Rendered = { path: string; target: string; bytes: number }

The text block reads Wrote <name> (<size>): <absolute path>.

Not in this release

Registered functions, host fonts, and remote transport.