erp2pdf-studio-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ERP2PDF_API_KEY | Yes | API token from the erp2pdf.com cabinet, issued with "Allow Template API". | |
| ERP2PDF_BASE_URL | No | Base URL of the erp2pdf.com deployment to talk to. | https://erp2pdf.com |
| ERP2PDF_OUTPUT_DIR | No | Where `render_preview` saves PDF and PNG previews. Created if missing, readable only by you. | ~/.cache/erp2pdf-studio-mcp (%LOCALAPPDATA%\erp2pdf-studio-mcp on Windows) |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_modelsA | List the Odoo models a template can bind to (live from the
customer's Odoo when a connector is configured, else bundled
samples). Use the |
| get_fieldsC | Fields of an Odoo model, plus |
| search_recordsA | Search real records in the customer's Odoo (needs a configured connector) to pick a record_id for get_values / render_preview. |
| get_sample_recordD | The record previews are rendered with (real when a connector is configured, else the bundled sample): shows the data shape. |
| list_templatesA | List the account's templates (id, name, bind_model, slot_count). |
| get_templateB | Get one template with its full layout and mapping. |
| create_templateB | Create a template from a Studio layout {bind_model, slots[], master_refs?, translations?}. The layout is validated first; on errors nothing is saved and the errors carry JSON paths. |
| update_templateA | Change a template. Either send a whole new |
| delete_templateC | Delete a template. |
| duplicate_templateC | Copy a template (default name: ' (copy)'). |
| validate_layoutA | Validate a layout without saving: returns {ok, errors[], warnings[], stats}. Each issue has a JSON path (slots[3].row_template[1].content), a code and a message. With evaluate=true every expression is also run against a sample record; runtime failures come back as warnings. |
| get_valuesA | What every {{ }} expression prints for one record, per slot
( |
| render_previewB | Render a preview (PREVIEW watermark, no credits) of a saved template (template_id) or an unsaved layout. output=html returns the HTML inline; pdf/png are saved to a local file and the path is returned (png = page 1). With output=png and show=true (default) the image itself comes back too: look at it to judge the design (alignment, overlaps, clipped text, contrast) and iterate. |
| list_startersB | Starting points: blank, quotation, invoice, purchase, product,
each with the |
| create_from_starterA | Create a template from a starter layout (same as Studio's New
template dialog). |
| get_capabilitiesA | Read this before designing. Everything a layout can hold, from
the same rules the validator applies: slot kinds and their keys with
types and allowed values (text: letterSpacing, lineHeight,
textTransform, valign, bgColor...; image: mask, grayscale; every
slot: opacity, shadow, rotation, blendMode), the paint format
(hex, theme., or a linear/radial gradient object), the |
| import_svgA | Turn an SVG (a logo, an illustration, a shape drawn elsewhere)
into a |
| preview_starterA | Look at a starter style before creating anything: page 1 on a fixed sample document, re-skinned by a palette and a font pairing (preset keys from list_starters), as an image. Width 240-960 px. Use it to compare styles and palettes with the user, then create_from_starter(starter, name, style=..., theme=palette). |
| list_partsA | List the shared header/footer parts (templates use them through layout.master_refs = {header: id, footer: id}). |
| create_partC | Create a header or footer part: {slots[]} in page coordinates (a header near the top, a footer near the bottom of the A4 page). |
| update_partB | Update a part's name, description and/or layout. Every template that uses the part changes with it. |
| delete_partA | Delete a part. Refused (part_in_use) while templates use it, unless force=true. |
| get_translationsA | Every translatable string of a PDF template (kind=pdf, header and
footer parts included) or an email template (kind=email: subject and
body text), with its translation per target language, a |
| set_translationsA | Translate a template, many languages in one call.
|
| list_email_templatesA | List the account's HTML email templates (sent from Odoo by the connector's 'Send by email' wizard). |
| get_email_templateB | Get one email template: subject, body_html, translations and the
record |
| create_email_templateB | Create an email template. Subject and body use the PDF templates' expressions: {{ expr }} prints a value HTML-escaped, {{{ expr }}} inserts it as cleaned HTML. Use inline styles and tables (email clients). {{ odoo_url }} is the connected Odoo's https address: {{ odoo_url }}/logo.png?company={{ company_id.id }} is the company logo. attach_template_id = a PDF template to attach when sent. |
| update_email_templateC | Change an email template; only the fields given change. remove_attachment=true stops attaching a PDF. |
| delete_email_templateD | Delete an email template. |
| preview_emailA | Render an email for one record: a saved one (email_template_id) or
a draft (subject + body_html, optional translations). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 30 tools
The surface splits cleanly into sub-domains (models/records, PDF templates, parts, starters, email templates, translations, preview/validation), and the descriptions explicitly cross-reference which tool to use when. A few boundaries blur: three creation paths (create_template, create_from_starter, duplicate_template) and three preview tools whose names invert verb placement (render_preview vs preview_starter/preview_email) could still cause misselection, as could the family of get_* tools (get_fields, get_capabilities, get_values, get_sample_record), which all mean different kinds of 'get'.
Nearly everything is snake_case with a leading verb, and the list_*/get_*/create_*/update_*/delete_* families are uniform across templates, parts, and email templates. The deviation is verb ordering in the preview trio (render_preview vs preview_starter, preview_email) and in create_from_starter, where the verb is followed by a preposition rather than a noun.
At 30 tools this sits above the comfortable band and is heavy for an agent to hold in working memory. The breadth is real (PDF design, shared parts, starters, SVG import, translations, email templates, preview, validation), and nearly every tool maps to a distinct operation, but some could consolidate — e.g. list_starters/preview_starter and create_template/create_from_starter.
CRUD is complete for PDF templates, shared parts, and email templates, and the design loop is closed by validate_layout, get_values, render_preview, and preview_email. Minor gaps remain: there is no get_part for fetching a single part, no duplicate for email templates, and no tool to inspect or edit existing translations per-cell beyond the bulk get/set pair, but these are workable.