Skip to main content
Glama
malinoto

tracepass-mcp-server

by malinoto

TracePass MCP Server

Listed on Glama

A Model Context Protocol server for TracePass — the EU Digital Product Passport platform. It lets AI assistants (Claude, Cursor, IDE agents) manage products, Digital Product Passports, economic-operator parties, and GS1 EPCIS 2.0 supply-chain events.

It speaks the full MCP protocol — tools, resources, resource templates, and prompts.

Two ways to use it

The same server core ships two ways:

  1. Hosted — point your MCP client at https://ai.tracepass.eu/mcp. Nothing to install; always current.

  2. Local (npm) — run tracepass-mcp-server via npx. The MCP client launches it as a subprocess and speaks MCP over stdio.

Related MCP server: fallpharm-mcp

Authentication

The server accepts either of TracePass's two v1 auth methods on the same Authorization: Bearer … header — it forwards whatever you send to the API, which decides. Pick the one that fits how you're connecting:

API key

OAuth 2.0

Best for

A single user, scripts, server-to-server

AI assistants / apps acting on a user's behalf

What you send

A static tp_… key as a Bearer token

A scoped access token obtained via the OAuth flow

Setup

Mint at Developer → API Keys

The user clicks Connect and approves scopes

Scope

All-or-nothing (the whole workspace)

Exactly the scopes the user granted; revocable

Works with

Hosted and local (npx)

Hosted endpoint only (needs a browser consent step)

Which should an AI assistant use? If your MCP client supports OAuth (Claude.ai, ChatGPT, and others), prefer OAuth — the user authorizes the connection once on a TracePass consent screen, you never handle a secret, and access is least-privilege and revocable. If your client only takes a header/token, use an API key.

No config beyond pointing your client at the hosted endpoint — discovery is automatic. On the first unauthenticated request the server returns a 401 whose WWW-Authenticate header carries a resource_metadata URL (RFC 9728) pointing at /.well-known/oauth-protected-resource, which names the TracePass authorization server. The client runs the standard authorization-code flow with PKCE (/api/oauth/authorize → /api/oauth/token), the user approves scopes, and the client stores + refreshes the token. If you distribute your own client, register an app under Developer → OAuth Apps to get a client_id; many hosted clients self-register via Dynamic Client Registration automatically.

Request only the scopes you need, e.g. passports:read passports:write offline_access. Users manage connected apps (and revoke) under Developer → OAuth Apps → Connected Apps.

API key

Mint a tp_… key under Developer → API Keys and send it as a Bearer token.

Hosted:

{
  "mcpServers": {
    "tracepass": {
      "url": "https://ai.tracepass.eu/mcp",
      "headers": { "Authorization": "Bearer tp_YOUR_KEY" }
    }
  }
}

Local (npx / stdio) — the local subprocess can't do an interactive OAuth consent step, so it's API-key only, via the TRACEPASS_API_KEY env:

{
  "mcpServers": {
    "tracepass": {
      "command": "npx",
      "args": ["-y", "tracepass-mcp-server"],
      "env": {
        "TRACEPASS_API_KEY": "tp_YOUR_KEY"
      }
    }
  }
}

Optional env vars:

Var

Default

Purpose

TRACEPASS_BASE_URL

https://app.tracepass.eu

Override the TracePass API base URL (e.g. point at a local stack).

TRACEPASS_AUTH_SERVER_URL

https://app.tracepass.eu

Public OAuth authorization-server origin advertised in discovery metadata. Set this when TRACEPASS_BASE_URL is an internal address.

MCP_BODY_LIMIT_BYTES

1048576 (1 MB)

Maximum request body size. Requests over the limit are rejected with 413 before reaching the SDK.

MCP_BATCH_LIMIT

10

Maximum JSON-RPC messages in a single batch request. Oversized batches are rejected with 400 batch_too_large.

PORT

8080

Listen port for the hosted HTTP service.

The hosted endpoint accepts POST only on /mcp, /compliance/mcp, and the supplier paths. GET and DELETE are rejected with 405 to prevent the SDK's stateless transport from opening an unbounded SSE stream.

Tools

The TracePass v1 API operations are grouped into 7 tools. Each takes an action enum plus action-specific arguments. The tools are:

  • tracepass_products - manage the product catalogue (list, get, create, create_batch, update, archive products).

  • tracepass_passports - manage Digital Product Passports (list, get, compliance check, registry-readiness check, place a battery passport on the market (async EU registry entry), get/set condition flags, create, suspend, archive, get QR, list snapshots, get snapshot), by id or by serial. Passports are identified via GS1 or four additional EN 18219 schemes (iso15459, iec61406, did, doi); battery passports accept only gs1 and iso15459 (Art. 77(3)). Condition flags are approved yes/no facts (e.g. battery: hasBMS, rechargeable, externalStorageOnly, isStationaryBess) that gate conditional legal duties — setting an approved flag may make additional fields required and block publishing if those fields are empty.

  • tracepass_passport_fields - update a passport's category-specific data fields, by id or by serial.

  • tracepass_passport_parties - set or remove a passport's economic-operator parties (manufacturer, importer, etc.).

  • tracepass_epcis - export, capture, and query a passport's GS1 EPCIS 2.0 supply-chain events.

  • tracepass_templates - list and get the DPP category field schemas, each field traced to the EU instrument that mandates it.

  • tracepass_scope - check whether a product type needs a Digital Product Passport (check), read the company's catalogue-wide scope report (catalogue_report), and trigger or poll a catalogue refresh run (catalogue_run, catalogue_run_status).

Each tool's full action set:

Tool

Actions

tracepass_products

list, get, create, create_batch, update, archive

tracepass_passports

list, get, get_by_serial, compliance, registry_readiness, place_on_market, get_condition_flags, get_condition_flags_by_serial, set_condition_flags, set_condition_flags_by_serial, capture_measurements, capture_measurements_by_serial, list_measurements, list_measurements_by_serial, latest_measurements, latest_measurements_by_serial, create, suspend, suspend_by_serial, archive, archive_by_serial, get_qr, get_qr_by_serial, list_snapshots, get_snapshot

tracepass_passport_fields

update, update_by_serial

tracepass_passport_parties

set, remove

tracepass_epcis

export, export_by_serial, capture, capture_job, query

tracepass_templates

list, get

tracepass_scope

check, catalogue_report, catalogue_run, catalogue_run_status

The *_by_serial actions address a passport by the customer's own serial number instead of its TracePass id. A serial is unique only within a GTIN, so if the same serial exists under two GTINs in your account a serial-only call returns 409 ambiguous_serial — pass the optional gtin arg to disambiguate (or use the by-id action). The same gtin disambiguator applies to every *_by_serial action.

The tracepass_passports compliance action returns a three-tier compliance verdict (compliant / compliant_with_warnings / incomplete) with regulation-cited findings — missing required fields, missing economic-operator parties, format issues, and per-category conditional rules. Read-only; use it to gap-check a passport, fix the cited gaps, then re-check.

A compliant verdict means this passport satisfies the rules encoded here, not this product may be placed on the market. The field specifications are hand-authored from the regulations, not an official EU artefact, and delegated acts are still landing. It is not legal advice.

Second-life batteries

A repurposed, remanufactured or reused battery needs a new passport linked to the original one(s) (Battery Regulation Art. 77(7)). Pass a lineage block to tracepass_passports create:

{ "predecessors": [ { "internalPassportId": "<your original passport id>", "trigger": "repurposing" } ] }

A predecessor is named by internalPassportId (one of your own passports) or by its resolvable identifier. trigger is one of preparation_for_reuse, preparation_for_repurposing, repurposing or remanufacturing. The platform derives batteryStatus from the triggers, stores the block immutably, and links your own originals back to the new passport (successors). A battery placed on the market before 18 Feb 2027 has no original passport: send an empty list with noPredecessorReason. Rule violations return 422 with the rule code.

Battery measurements (living record)

capture_measurements pushes over-life data from your own equipment into a published battery passport: state of health, fades, cycle counts, dynamic values, state of charge, negative events, temperature history (Battery Regulation Annex XIII point 4). Every measurement is kept; the newest per field becomes the passport's current value and sets dynamicDataAsOf. list_measurements and latest_measurements read them back.

They are metered against the plan's monthly measurement allowance, not the daily write budget. Paid plans keep counting past the allowance at no charge; the Free plan stops at its allowance. Reading a passport is never metered.

A note on writes

Some actions cost money or are irreversible — the server's tool descriptions tell the model so:

  • tracepass_passports create makes a draft passport. A draft takes no plan DPP slot and is not billed; the slot, and any overage past the plan cap, is taken when the passport is published in the TracePass dashboard. Each create counts against the daily write budget.

  • tracepass_passports archive is irreversible — the public QR permanently 404s. Use suspend (reversible) when a change might be undone.

  • tracepass_epcis — export, capture and query are on every plan, Free included; captured events count against the plan's event allowance, and capture over it returns an overage or hard-block message.

Resources

Read-only entity data you can attach as conversation context:

  • tracepass://products — the product catalogue

  • tracepass://product/{id} — one product

  • tracepass://passport/{id} — one passport, full field detail

  • tracepass://passport/{id}/epcis — a passport's EPCIS 2.0 events

  • tracepass://passport/{id}/compliance — a passport's compliance verdict

  • tracepass://passport/{id}/registry-readiness — a mechanical pre-submission check modelled on the EU DPP Registry's formal gate: mandatory-field presence, formatting, a resolvable public link, item-level granularity, and a well-formed commodity code only where the category carries one (none for batteries: a battery passport's registration identifier is not entered in the customs declaration). Not the substantive compliance verdict, and not a prediction of the real registry's response — its registration API has no published spec. Battery only.

  • tracepass://passport/{id}/snapshots — the snapshot history of a passport (newest first): a snapshot on publish and after every change to a non-draft passport; each entry carries version, reason (e.g. published, field_edit, status_change, baseline), actor, snapshotAt, contentHash, hashValid (re-verified on read), restorable flag, and field count.

  • tracepass://templates — all 13 DPP category field schemas

  • tracepass://template/{category} — one category's full field schema

Prompts

Reusable DPP workflows the client surfaces as slash-commands:

  • audit_passport — review a passport for completeness and compliance readiness

  • onboard_product — create a product and its first passport

  • explain_dpp_requirements — explain what a category's compliant DPP must contain, and the regulation behind each field

  • compliance_gap_check — produce a prioritised, regulation-cited list of what's blocking a passport's compliant publication

  • review_epcis_events — summarise a passport's supply-chain trail

For suppliers: answering a data request

A second, separate endpoint serves suppliers who receive a TracePass data request. It is not part of the tools above. The request email carries a personal address:

https://ai.tracepass.eu/supplier/mcp/<token>

Add it to an AI assistant as a custom connector. For clients that can set headers, https://ai.tracepass.eu/supplier/mcp with Authorization: Bearer <token> works too. The token authorises that one request only; there is no account and no OAuth. The assistant can then:

Tool

What it does

get_request

Start here: who is asking, for which product, and every field asked for, each with its meaning, unit, format and legal source; plus answers already sent and the review outcome

validate_answers

A dry run: what would be stored, which keys were not requested, and what does not fit. Writes nothing

get_upload_command

The best way to attach a datasheet or certificate when the assistant can run shell commands: returns a curl command that uploads the file from disk and prints a documentId to cite (PDF, Office, CSV, PNG/JPEG/WebP)

upload_evidence

Attach a very small file (a few kilobytes) inline as base64; prefer get_upload_command, or cite a URL or note

submit_answers

Send answers with evidence per value to the requester's human review; can be repeated (answers merge) until reviewed

get_review_status

Whether the requester has reviewed them, the outcome, accepted fields, and when the link expires

Answers go to the requester's human review; they never publish anything on their own.

DPP Assistant: EU passport questions

A third endpoint answers questions about EU Digital Product Passport law for anyone with a free TracePass account:

https://ai.tracepass.eu/compliance/mcp

Add it to an AI assistant as a custom connector (in Claude: Customize → Connectors → "+ Add" → "Add custom connector"), then sign in with a TracePass account when asked. It uses OAuth; no API key is needed. Answers cite their source, and each company gets about 100 answers a day. Full guide: tracepass.eu/docs/dpp-assistant.

Tool

What it does

scope_check

Whether EU law requires a passport for a type of product, from when, and what it requires of each role

required_fields

The data a passport must contain for a category, with the article requiring each field and who may see it

what_changed

Changes in EU passport law and standards for your categories since a date; planned items are marked as not yet law

registry_guidance

The EU DPP Registry and the technical side: registration, identifiers, data carriers, formats and standards

create_draft_passport

Creates a draft passport in your own account; publishing stays with you in TracePass

report_answer

Reports an answer you think is wrong or unclear, for review

get_profile, update_profile, delete_profile

The company facts the assistant remembers between questions, so you do not repeat them

Development

npm install
npm run build        # tsc -> dist/
npm run typecheck
npm test             # vitest
npm run lint
npm start            # run the hosted HTTP service locally (:8080)
npm run start:stdio  # run the stdio server locally

The hosted service is a plain Node HTTP server (dist/http.js), stateless — each request carries its own API key and builds a fresh MCP session. It is containerised via the Dockerfile; the hosted endpoint runs in the EU.

Listed on Glama

This server is published in the official MCP Registry as eu.tracepass/tracepass and listed on Glama:

TracePass MCP server

License

MIT

Available Tools

7 tools
tracepass_epcisTracePass EPCIS 2.0AInspect

GS1 EPCIS 2.0 supply-chain events. export, capture, capture_job and query are on every plan, Free included. Captured events count against the plan's event allowance (10 a month on Free); over it, capture returns an overage or hard-block message.

Actions (pass via action, with args):

  • export — args: { id }. Export a passport's events as an EPCIS 2.0 JSON-LD document. Read-only.

  • export_by_serial — args: { serial, gtin? }. Same as export, addressed by your own serial. A serial is unique only WITHIN a GTIN — if it isn't unique in your account the call returns 409 ambiguous_serial; pass gtin (or use export by id). Read-only.

  • capture — args: { events }. events is an EPCISDocument, a single event, or an array of events (JSON-LD). Returns a 202 with a captureJobId.

  • capture_job — args: { jobId }. Poll an async capture job. Read-only.

  • query — args: { params? }. params is a key/value map of standard EPCIS query parameters (EQ_bizStep, GE_eventTime, MATCH_epc, …). Read-only.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action`.
actionYesEPCIS 2.0: export a passport's events (export | export_by_serial), capture new events, poll a capture job, or query events.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the top-level annotations (readOnlyHint=false with no per-action nuance) by labeling export, export_by_serial, capture_job and query individually as read-only. It also discloses quota behavior (10/month Free, overage or hard-block on capture), the 202 + captureJobId async pattern, and the 409 ambiguous_serial failure mode — none of which is derivable from annotations or schema.

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?

Front-loaded with the resource, the action list, and the plan/quota caveat, then a scannable per-action bullet block. Nearly every sentence earns its place; the plan-allowance sentence is the only one that leans informational rather than operational.

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?

An output schema exists, so return shapes need not be described, and the description instead covers what the schema can't: quota enforcement, the async job-poll workflow, and the ambiguity error with its remedy. Nothing an agent needs in order to invoke an action correctly is absent.

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?

Schema coverage is 100%, so 3 is the floor, but the description adds real meaning: `events` may be an EPCISDocument, a single event, or an array; `params` is a standard EPCIS query map with concrete examples (EQ_bizStep, GE_eventTime, MATCH_epc); and `serial` uniqueness is scoped WITHIN a GTIN. That last point is the key semantic the schema only hints at.

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 the resource precisely (GS1 EPCIS 2.0 supply-chain events) and enumerates five named actions with their argument shapes. No sibling tool covers EPCIS events, so the domain boundary is unambiguous from the name plus first sentence.

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?

Each action carries its required args and a routing hint: export vs export_by_serial is disambiguated, and the 409 ambiguous_serial case explicitly redirects to passing `gtin` or using export by id. What's missing is guidance on when to pick `query` over `export`/`export_by_serial` for retrieving events.

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

tracepass_passport_fieldsTracePass passport fieldsA
DestructiveIdempotent
Inspect

Update field values on a Digital Product Passport. Every change is recorded in the passport's audit trail with the credential that made it (API key or connected app) and this MCP channel.

source (optional) says where the value came from. Omit it, or pass "manual", when the user gave you the value or it comes from their own records: it is written with the user's rights (approved for an API key or an admin; sent to review for a connected app acting for an editor). Pass "ai_suggested" when you found or inferred the value yourself (web research, reading a document): it lands in the dashboard review queue for a human to approve, and it is refused on fields only the economic operator may state or that must be measured (e.g. battery stateOfHealth).

Actions (pass via action, with args):

  • update — args: { id, fieldKey, value, source? }. value type matches the field's dataType (string, number, boolean, array, object).

  • update_by_serial — args: { serial, fieldKey, value, gtin?, source? }. Same as update, addressed by your own serial. A serial is unique only WITHIN a GTIN — if it isn't unique in your account the call returns 409 ambiguous_serial; pass gtin (or use update by id) to resolve exactly.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action`.
actionYesUpdate one passport field, addressed by passport id (update) or by your serial (update_by_serial).

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A5/5.0
Behavior5/5

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

Beyond annotations, it discloses that every change is recorded in an audit trail with credential and channel information, that `ai_suggested` values enter a human review queue, that some fields are refused for AI-suggested values, and that ambiguous serials return 409. These are important behavioral details not captured by 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 dense but well-structured. It front-loads the core purpose, then uses a clearly delimited paragraph for `source` semantics and a bulleted list for actions. Each section carries necessary operational information without filler.

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 nested schema, rich annotations, output schema, and mutation semantics, the description covers everything an agent needs: action selection, argument requirements, source behavior, audit implications, and error handling for ambiguous serials.

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

Parameters5/5

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

Although schema coverage is 100%, the description adds substantial semantic value: it explains what `source` means in practice, why `gtin` may be needed, how `value` type depends on the field's dataType, and which args belong to each action. This goes well beyond the schema's field descriptions.

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 opens with a specific verb and resource: 'Update field values on a Digital Product Passport.' It clearly distinguishes the tool from broader passport/product tools by focusing on field-level mutation, and it names the two supported actions.

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

Usage Guidelines5/5

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

It explicitly explains when to use `update` versus `update_by_serial`, when to pass `gtin` to resolve a 409 ambiguous_serial, and when to use `manual` versus `ai_suggested` based on who supplied the value. The guidance is precise and actionable.

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

tracepass_passport_partiesTracePass passport partiesA
DestructiveIdempotent
Inspect

Manage the economic-operator parties on a passport — manufacturer, importer, authorisedRepresentative, distributor, recycler, producerResponsibilityOrg. Each party carries a legal name and at least one identifier.

Identifier rules (EN 18219 §6.2–6.5): a party needs at least one of gln, legacyOperatorId, or operatorIdentifier. If both gln and operatorIdentifier (scheme gln) are provided they must agree — a mismatch returns 400. An operatorIdentifier of scheme gln also fills the top-level gln field; facilityIdentifier never does. Typed identifiers (operatorIdentifier / facilityIdentifier) are not set by AI extraction or CSV import.

operatorIdentifier schemes: • iso6523 — { scheme:"iso6523", icd:"<4 digits>", value } — ICD 0199 = LEI (ISO 17442), 0088 = GLN, 0060 = DUNS. • gln — { scheme:"gln", gln:"<13 digits>" } — also fills top-level gln. • did — { scheme:"did", did:"did::" } — syntax-checked only (EN 18219 §6.4.2(b)). • doi — { scheme:"doi", doi:"10./" } — doi:/https://doi.org/ prefix accepted and stripped.

facilityIdentifier schemes: same four; the gln variant also accepts optional extension (GS1 SGLN sub-location).

Actions (pass via action, with args):

  • set — args: { id, role, legalName, gln?, country?, url?, tradeName?, postalAddress?, email?, legacyOperatorId?, operatorIdentifier?, facilityIdentifier? }. Sets or updates one role. tradeName, postalAddress and email are shown on the public passport; for a battery importer they are its Battery Regulation Art. 41(3) details.

  • remove — args: { id, role }. Clears one role. Once a battery passport is placed on the market, a change to a stored operatorIdentifier or facilityIdentifier returns 409 operator_locked; other party edits stay allowed. To correct a locked identifier, the passport is marked for deletion and a new one created.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action`.
actionYesSet (add/replace) or remove an economic-operator party on a passport by its role.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A4.3/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses the 400 returned on gln/operatorIdentifier mismatch, the 409 operator_locked condition after market placement, which fields become public on the passport, and that typed identifiers are never populated by AI extraction or CSV import. This is exactly the operational context the destructive/idempotent hints cannot convey.

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?

Long but deliberately structured with labelled sections and bullets, and the identifier rules are genuinely load-bearing for correct invocation. The action list sits after the identifier rules rather than up front, and several sentences restate what the nested schema already says.

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?

An output schema exists and annotations cover the safety profile, so the description's remaining burden is mutation semantics and failure modes — both covered (400 mismatch, 409 lock, public-field visibility, non-AI-populated identifiers). Nothing an agent needs to call this correctly is missing.

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?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning: the EN 18219 identifier rules, the ICD table (0199=LEI, 0088=GLN, 0060=DUNS), doi prefix stripping, and the side effect that scheme gln fills the top-level `gln` while facilityIdentifier never does. It largely mirrors the nested-schema text, which keeps it from a 5.

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?

Opens with a specific verb+resource ("Manage the economic-operator parties on a passport") and enumerates the exact roles covered, plus the two actions set/remove. The scope is unmistakably about party records rather than general passport fields, but it never names the sibling tool (tracepass_passport_fields) that an agent might reach for instead.

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 concrete per-action guidance (args for `set` vs `remove`), states that `set` both creates and updates a role, and describes the recovery path when an identifier is locked ("the passport is marked for deletion and a new one created"). It stops short of explicit when-not-to-use or sibling alternatives.

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

tracepass_passportsTracePass passportsA
Destructive
Inspect

Manage Digital Product Passports — create, read, and run lifecycle actions.

IMPORTANT: create makes a DRAFT passport. A draft takes no plan DPP slot and is never billed; the slot, and any per-DPP overage past the plan cap, is taken when the passport is published, which happens in the TracePass dashboard, not through this tool. Each create counts against the daily write budget. archive is IRREVERSIBLE (the public QR permanently 404s); prefer suspend when a change might be undone.

IDENTIFIER SCHEMES (EN 18219): passports are identified by one of five schemes. Battery passports (Battery Regulation Art. 77(3)) accept ONLY gs1 and iso15459. • gs1 — { scheme:"gs1", gtin, serialNumber } — GS1 GTIN + serial; gtin is 8/12/13/14 digits, stored as GTIN-14. • iso15459 — { scheme:"iso15459", issuingAgencyCode, primaryId, serial? } — ISO/IEC 15459; the server derives raw (IAC + primaryId + serial). • iec61406 — { scheme:"iec61406", uri } — IEC 61406 Identification Link (https URI). Not valid for batteries. • did — { scheme:"did", did, method } — W3C DID Core. Not valid for batteries. • doi — { scheme:"doi", doi, granularity:"model"|"batch"|"item" } — ISO 26324 DOI, stored as bare 10./ (any https://doi.org/ or doi: prefix stripped on input; resolves as https://doi.org/); granularity REQUIRED per EN 18219 §5.6.2(b). Not valid for batteries. The legacy top-level gtin + serialNumber pair is still accepted as a deprecated alias for scheme:"gs1".

Actions (pass via action, with args):

  • list — args: { page?, limit? (≤100), productId?, status?, search? }. status ∈ draft|in_review|approved|published|suspended|expired|archived. Read-only.

  • get — args: { id, format? (summary|full), lang? }. Read-only. Response includes identifier, identifierKey, and (for GS1 passports) gs1.

  • get_by_serial — args: { serial, format?, lang?, gtin? }. Read-only. Addresses the passport by your own serial. A serial is unique only WITHIN a GTIN — if the same serial exists under two GTINs in your account the call returns 409 ambiguous_serial; pass gtin (or use the by-id action) to resolve exactly.

  • compliance — args: { id }. Read-only. Returns a three-tier compliance verdict (compliant | compliant_with_warnings | incomplete) with regulation-cited findings — use to gap-check a passport against the rules for its category, fix the cited fields/parties, then re-check. Also returns byRegulation[]: the same findings grouped per regulation, worst first, so you can tell WHICH regime is failing instead of reading one incomplete as everything being wrong. A regulation absent from that array raised no finding — that is not the same as it having passed.

  • registry_readiness — args: { id }. Read-only. Returns { ready, findings[] } — whether the passport would pass the EU DPP Registry's FORMAL submission gate (mandatory fields present, correct formatting, a resolvable public link, item-level granularity via a serial number, and a well-formed commodity code where the category carries one, and, for EV, LMT and industrial (over 2 kWh) batteries, conformance to the Commission's battery data model that the Registry validates against (REG-READY-SEMANTIC)). This is the registry's mechanical pre-submission check, NOT the substantive compliance verdict; a passport can be registry-ready yet not substantively compliant. Battery passports only.

  • place_on_market — args: { id }. WRITE, battery passports only, published only. Places the passport on the market: registers it in the EU DPP registry under the account's own registry access (the upload Battery Regulation Art. 77(10) requires of the operator placing the battery on the market). A legal act for the economic operator — confirm with the user first. ASYNCHRONOUS: answers 202 { passport, passportId, status: "placing", dppId } and the registry call follows in the background; read the passport (get) to follow placeOnMarketStatus: placing → placed (placedOnMarketAt, registrationId) or rejected (registrationRejectionReason). To retry a rejected passport, fix the cause and call place_on_market again. Refusals are 409 with a code: not_a_battery | not_published | already_placed (placing or placed) | operator_id_missing (no economic-operator identifier on the account) | registry_not_configured (an admin sets registry access in the dashboard) | registry_not_ready (findings[] lists what stands in the way — run registry_readiness for the structured findings; an empty list means the configured registry is not open to submissions from TracePass yet). After placement the passport's party operatorIdentifier / facilityIdentifier are locked (409 operator_locked on a change). Counts 1 write.

  • create — args: { productId, identifier?, gtin?, serialNumber?, lineage? }. Creates a draft (not billed). Provide identifier (preferred) or legacy gtin + serialNumber. Battery passports accept only gs1 and iso15459 schemes — other schemes return 400. A duplicate identifier returns 409. lineage (battery only) — a repurposed, remanufactured or reused battery needs a NEW passport linked to the original(s) (Battery Regulation Art. 77(7)): { predecessors: [ { internalPassportId? | identifier?, trigger: preparation_for_reuse|preparation_for_repurposing|repurposing|remanufacturing } ] (≤10), noPredecessorReason? (only with an empty list, e.g. placed on the market before 18 Feb 2027) }. The server derives batteryStatus from the triggers and links your own predecessor passports back. Immutable after create. Rule violations return 422 with the rule code (duplicate_predecessor, predecessor_not_found, status_trigger_mismatch, …).

  • suspend — args: { id }. Reversible — public QR shows 'suspended'.

  • suspend_by_serial — args: { serial, gtin? }. Same as suspend, addressed by your serial. 409 ambiguous_serial if the serial isn't unique in your account — pass gtin.

  • archive — args: { id, reason? (recycled|never_placed|duplicate_or_error) }. IRREVERSIBLE and destructive — confirm with the user first. reason is REQUIRED for battery passports (400 reason_required / invalid_reason without a valid one): recycled, never_placed (never placed on the market or put into service), or duplicate_or_error (a duplicate or erroneous record); for other categories it is optional. A passport marked for deletion cannot be archived (409).

  • archive_by_serial — args: { serial, gtin?, reason? }. IRREVERSIBLE and destructive, addressed by your serial — confirm first. Same reason rule as archive. 409 ambiguous_serial if the serial isn't unique — pass gtin.

  • get_qr — args: { id, format? (svg|png), symbology? (qr|datamatrix) }. Read-only. symbology=datamatrix renders an ISO/IEC 16022 Data Matrix instead of a QR (EN 18220 permits both; same passport URL).

  • get_qr_by_serial — args: { serial, format? (svg|png), symbology? (qr|datamatrix), gtin? }. Read-only. Same as get_qr, addressed by your own serial. A serial is unique only WITHIN a GTIN — if the same serial exists under two GTINs in your account the call returns 409 ambiguous_serial; pass gtin (or use get_qr by id) to resolve exactly.

  • list_snapshots — args: { id, page?, limit? (≤100), at? (ISO 8601) }. Read-only. Returns a paginated list of snapshots for the passport (newest first). A snapshot is written on publish and after every change to a non-draft passport (EN 18221 change archive); each carries id, version, reason (e.g. published|field_edit|status_change|baseline), actor (who caused it, when known), snapshotAt, contentHash, hashValid (re-verified on every read), restorable, fieldCount. With at, returns instead the single snapshot valid at that instant (full record plus validFrom/validUntil) — answers "what did this passport say on date D"; 404 before the first snapshot. Counts 1 against the daily read budget.

  • get_snapshot — args: { id, snapshotId }. Read-only. Returns the full archival record of one snapshot: the complete JSON-LD the passport asserted at that time, plus hash and hashValid. Counts 1 against the daily read budget.

  • get_condition_flags — args: { id }. Read-only. Returns the resolved condition profile Record<flagKey,{value,status,source}>. Condition flags are reviewer-approved yes/no facts gating conditional legal duties. Battery flags: hasBMS, rechargeable, externalStorageOnly, isStationaryBess. An approved flag makes specific fields required — a missing gated field is a hard publish block (conditional_missing). Counts 1 against the daily read budget.

  • get_condition_flags_by_serial — args: { serial, gtin? }. Read-only. Same as get_condition_flags, addressed by your own serial. 409 ambiguous_serial if serial not unique — pass gtin.

  • set_condition_flags — args: { id, flags: Record<flagKey, boolean|null> }. WRITE. Set or clear condition flags (null clears). Keys must be registered for the passport category (battery: hasBMS, rechargeable, externalStorageOnly, isStationaryBess). WARNING: approving a flag can make fields required and block publishing if those fields are empty — fix any gated fields before or immediately after setting the flag. Writes are approved + audited. Idempotency-Key supported. Counts 1 write.

  • set_condition_flags_by_serial — args: { serial, gtin?, flags }. WRITE. Same as set_condition_flags, addressed by your own serial. 409 ambiguous_serial if serial not unique — pass gtin.

  • capture_measurements — args: { id, measurements: [ { fieldKey, value, measuredAt (ISO 8601), externalId?, unit? } ] (≤500) }. WRITE, battery passports only, published only. Pushes over-life measurements from the customer's own equipment (e.g. a BMS reporting stateOfHealth, numberOfFullEquivalentChargingCycles; the Annex XIII point 4 use-data keys). Every measurement is stored; the newest per field becomes the passport's current value and sets dynamicDataAsOf. externalId makes a measurement idempotent. A value may be at most 16 KB serialised. batteryStatus is NOT a measurement (400 invalid_field_key). A key the Regulation keeps off this battery category returns 422 field_not_applicable (e.g. stateOfCertifiedEnergy on an LMT battery). Metered against the plan's monthly measurement allowance, not the daily write budget: paid plans keep counting past it at no charge; Free stops at its allowance. Reading a passport is never metered.

  • capture_measurements_by_serial — args: { serial, gtin?, measurements }. Same, addressed by your own serial.

  • list_measurements — args: { id, fieldKey?, from?, to? (ISO 8601), limit? (≤200), cursor? }. Read-only. Measurement history, newest first; page with the returned nextCursor.

  • list_measurements_by_serial — args: { serial, gtin?, fieldKey?, from?, to?, limit?, cursor? }. Read-only.

  • latest_measurements — args: { id }. Read-only. The newest measurement per accepted key (null where none yet).

  • latest_measurements_by_serial — args: { serial, gtin? }. Read-only.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action` (see each action above).
actionYesWhich passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (a draft, not billed). Lifecycle: place_on_market (battery, published; async EU registry entry — confirm first) | suspend (reversible) | archive (IRREVERSIBLE; battery passports need `reason`), the last two each with a _by_serial variant.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A3.9/5.0
Behavior4/5

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

Adds substantial context the coarse annotations (destructiveHint=true covers 25 heterogeneous actions) cannot convey: drafts take no slot and are never billed, the slot is consumed on publish in the dashboard, archive permanently 404s the public QR, place_on_market is async (202 → placing/placed/rejected) and locks operator identifiers, and measurements are metered against a separate allowance. Deducting one point only because the per-action read/write labels are scattered across a very long body rather than summarized up front, making the destructive surface easy to miss.

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?

Front-loading is good — the draft/billing and archive-irreversibility warnings come before anything else, and headers plus bullets make a 25-action surface navigable. However the body is very long and duplicates structured data it does not need to restate (the archive reason enum, the measurements array shape, the action enum), so a meaningful share of sentences do not earn their place.

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?

An output schema exists, yet the description still explains return shapes (compliance's three-tier verdict and byRegulation[], registry_readiness { ready, findings[] }, snapshot fields) — helpful but partly redundant. For a 25-action dispatcher with nested args, the coverage of error codes, limits, and preconditions is thorough enough that an agent could call any action correctly.

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?

Schema coverage is 100%, so the baseline is 3, but the description genuinely adds meaning: GTIN stored as GTIN-14, DOI prefixes stripped on input, granularity required per EN 18219 §5.6.2(b), battery passports restricted to gs1/iso15459, lineage capped at 10 predecessors and immutable after create, and reason required only for battery passports. It does repeat several schema facts (the reason enum, measurements shape), which keeps it from a 5.

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?

Opens with a specific verb+resource statement ("Manage Digital Product Passports — create, read, and run lifecycle actions") and then enumerates all 25 actions with concrete semantics, so an agent knows exactly what domain this covers. The only gap at the 5 level is that it never distinguishes itself from the siblings (tracepass_passport_fields, tracepass_passport_parties, tracepass_epcis), so an agent must infer that field/party edits live elsewhere.

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?

Intra-tool routing is unusually explicit: suspend vs archive ("prefer `suspend` when a change might be undone"), compliance vs registry_readiness ("mechanical pre-submission check, NOT the substantive compliance verdict"), by-id vs by-serial (409 ambiguous_serial, pass `gtin`), and confirm-before-place_on_market. What is missing is cross-tool guidance — nothing says when to reach for this tool rather than a sibling.

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

tracepass_productsTracePass productsA
Destructive
Inspect

Manage the TracePass product catalogue. A product is the catalogue layer — one product can have many passports (one per serialised unit). Products are not billable on their own.

Actions (pass via action, with args):

  • list — args: { page?, limit? (≤100), category?, status?, search? }. Read-only.

  • get — args: { id }. Read-only.

  • create — args: { name, model, category, description? }. category is one of: battery, textile, electronics, construction, steel, detergents, paints-coatings, packaging, furniture, tyres, jewelry, toys, fmcg.

  • update — args: { id, name?, model?, description? }; pass at least one field to change.

  • create_batch — args: { products: [ { name, model, category, description? }, … ] }, up to 100. Partial-success: the response carries a per-item status, so some items can be created while others error. The whole batch consumes N writes upfront; if that would exceed the daily cap NOTHING is created (429).

  • archive — args: { id }. Soft-archive a product. Blocked with 409 while any non-archived passport still references it — archive those passports first. This is reversible and is NOT deletion.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action` (see each action above).
actionYesWhich product operation to run: list | get | create | create_batch | update | archive.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond the annotations: create_batch partial-success semantics, per-item statuses, the N-writes-upfront reservation rule and the 429 fail-closed behavior, the 409 guard, and explicit reversibility ('This is reversible and is NOT deletion') for archive. These are exactly the operational traits an agent cannot infer from the schema.

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?

Front-loaded with the domain model, then a scannable per-action bullet list. Every line carries a constraint, enum, or failure mode; there is no filler prose despite the density.

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?

An output schema exists so return values need no explanation, yet the description still flags the one output detail that matters operationally (per-item status in batch responses). Combined with the write-cap, conflict, and reversibility notes, nothing an agent needs is missing.

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?

Schema coverage is 100%, so baseline is 3. The description still adds action-scoped meaning the schema cannot express, such as which fields are required per action and 'pass at least one field to change' for update, though the category enum and limit≤100 are restatements of the schema.

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 the resource (TracePass product catalogue) and defines it precisely against the adjacent concept: 'one product can have many passports (one per serialised unit)'. That single clause removes the ambiguity with the sibling tracepass_passports tool, and the action list spells out the verb set.

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

Usage Guidelines5/5

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

Each action carries its own argument contract and preconditions: archive is blocked with 409 while a non-archived passport references the product, with an explicit instruction to archive passports first. It also states the products/limit cap and that products are not billable, so the agent knows when this tool is not the right lever.

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

tracepass_scopeTracePass DPP scope checkerAInspect

Check what EU law says for a product type matching the facts given: whether it needs a Digital Product Passport, from when, at which level, under which act and article, and the duties of each role. Also read the company's catalogue-wide scope report and trigger a catalogue refresh run.

HARD RULES — always apply these to scope answers:

  • Answers state what the law says for product types matching the given facts. This is not legal advice; never write 'you must' — use product-type phrasing ('LMT batteries need a passport from 18 February 2027, Battery Regulation Art. 77(1)').

  • Cite the article the answer gives for every verdict and duty. A regulation without an article is not a citation. A not_covered answer rests on no article: say our rules do not cover the product and name the nearest act it gives, never cite that act as the basis.

  • A date with precision 'quarter', 'month' or 'year' is a plan, NEVER a deadline or a start date. Write 'planned for Q2 2027 (planned, not law yet)', never 'from', 'by' or 'deadline'.

  • Relay not_covered and needs_input as the results they are, never as errors. not_covered = the product falls outside these scope rules. needs_input = blocking questions remain unanswered — relay the questions in ask[] to the user before giving a verdict.

  • Items in an act's planned list are not law yet: always label them 'Planned, not law yet' (labelText), with their wording.

  • ruleStatus: 'needs_recheck' means the law behind an act changed and our rules for it are being re-checked (since recheckSince): say so with the answer.

Actions (pass via action, with args):

  • check — args: { category?, facts?, role?, placedOnMarket?, lifecycleEvent?, contains?, productId?, passportId?, locale? }. Ask whether a product type needs a DPP. Available on every plan, Free included. Counts against the per-company scope-answer cap (~100/day, 30/min burst), NOT the v1 read/write budget. 429 scope_answer_cap when the daily cap is spent. not_covered and needs_input are 200 results, not errors. category: one of battery | detergents | toys | construction | textile | steel | tyres | furniture | electronics | packaging | paints-coatings | jewelry | fmcg | vehicles | other. facts: namespace-prefixed keys from the loaded rules (e.g. battery.use, battery.capacityKWh). Unknown keys or wrong values return 400 invalid_input. role: your role in the act's terms: manufacturer | importer | distributor | authorised_representative | fulfilment_service_provider. Selling under your own name = manufacturer with facts.ownBrand: true. Omit to list every role's duties. placedOnMarket: { date: 'YYYY-MM-DD' | 'YYYY-MM' | 'YYYY', precision?: 'day'|'month'|'year' } or null. contains: array (≤5) of component queries — use to ask about a battery inside a toy: [ { label?, facts? } ]. locale: en | bg | de | it (default: from Accept-Language header, else en).

  • catalogue_report — args: { classification?, category?, act?, changed?, q?, cursor?, limit? (≤500) }. Read the catalogue-wide scope report (one row per product). Requires the Growth plan or above; 403 plan_upgrade_required below Growth — tell the user this needs a plan upgrade, do not retry. Counts 1 against the daily read budget per page. classification filter: missing | draft_only | published_incomplete | published | not_required | open_questions | not_covered. Response: { run, running, totals, items: [{ productId, passportIds, gtin, category, summary, classification, changedAt }], nextCursor, disclaimer }. Full answer for one product: call check with that productId.

  • catalogue_run — args: {}. Start a catalogue scope refresh run (also runs nightly). Returns 202 { runId, status }; poll with catalogue_run_status. Requires Growth plan. 409 run_in_progress if already active; 429 run_cooldown with retryAfter within 10 minutes of a finished run.

  • catalogue_run_status — args: { runId }. Get the status (queued | running | done | failed) and result counts for one catalogue run. Requires Growth plan.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; required fields depend on `action` (see above).
actionYesWhich scope operation to run: check | catalogue_report | catalogue_run | catalogue_run_status.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A4.4/5.0
Behavior5/5

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

Goes well past the annotations with operational detail an agent cannot infer: per-company cap (~100/day, 30/min burst, 429 scope_answer_cap), that scope answers do NOT draw on the v1 read/write budget, 202 + polling for catalogue_run, 409 run_in_progress, 429 run_cooldown with retryAfter inside 10 minutes, and that not_covered/needs_input are 200 results rather than errors. It also explains the semantics of ruleStatus 'needs_recheck' and the 'planned' list, which are domain behaviours, not schema facts. Nothing here contradicts the annotations (readOnlyHint=false is consistent with catalogue_run starting a run).

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?

Purpose is front-loaded and the HARD RULES are operationally necessary, but the text is long and repeats itself: 'not_covered and needs_input are 200 results, not errors' appears in the rules and again under check, and 'Requires Growth plan' is restated for three separate actions. Trimming that duplication would lose no information.

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?

Although an output schema exists, the description still sketches the catalogue_report payload ({ run, running, totals, items, nextCursor, disclaimer }) and covers the parts an agent could otherwise get wrong: plan gating, error codes, polling flow, and how to phrase legal verdicts. For a four-action dispatcher with nested args this is complete.

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

Parameters5/5

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

Schema coverage is 100%, so 3 is the floor, but the description adds real meaning: the full category enum, that facts keys are namespace-prefixed ('battery.use', 'battery.capacityKWh') and that unknown keys or wrong values yield 400 invalid_input, that ownBrand:true maps to manufacturer, and that placedOnMarket precision changes whether a date is a plan or a deadline. It also documents the 5-item cap on contains and the meaning of limit ≤500.

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 opening sentence names a specific verb and resource ('check what EU law says for a product type… whether it needs a Digital Product Passport') and the Actions block enumerates all four operations (check, catalogue_report, catalogue_run, catalogue_run_status), so the multi-action surface is unambiguous. It never references the sibling tools (tracepass_passports, tracepass_products, tracepass_epcis), so an agent gets no explicit help separating this from them.

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?

Each action carries routing context: 'Full answer for one product: call check with that productId', 'poll with catalogue_run_status', and plan thresholds ('Requires the Growth plan or above; 403 plan_upgrade_required below Growth — tell the user this needs a plan upgrade, do not retry'). What is missing is guidance relative to the sibling tools — nothing says when to use tracepass_scope versus tracepass_passports for the same underlying data.

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

tracepass_templatesTracePass DPP templates (regulatory schemas)A
Read-onlyIdempotent
Inspect

Discover the regulatory field schema for each DPP category — what a COMPLIANT passport must contain, per the governing EU regulation. Read-only reference data. Use this to advise on requirements before creating products/passports, and to gap-check a draft against the rules.

Actions (pass via action, with args):

  • list — args: {}. Lists all 13 categories with their field count, required-field count, and governing regulation (name + number + effective/mandatory dates).

  • get — args: { category }. Full field schema for one category: every field's key, label, dataType, whether it is REQUIRED, its access level (public/restricted/authority), enum options, validation bounds, and — where known — the regulation article/annex that mandates it. category is one of: battery, textile, electronics, construction, steel, detergents, paints-coatings, packaging, furniture, tyres, jewelry, toys, fmcg.

BATTERY — required-ness is per-category, so required alone is the wrong answer. Resolve it in this order:

  1. SCOPE FIRST. Only EV, LMT and industrial_gt_2kwh batteries owe a passport at all (Art. 77(1), Reg (EU) 2023/1542). For portable, SLI or industrial_lte_2kwh, NO field is required — do not list mandatory fields for them; say the battery is out of scope.

  2. Then requiredBy[batteryCategory] where the field carries that map (required | conditional | notApplicable). conditional means owed only when a fact holds (a commercial warranty offered, a BMS present, the battery in service); an approved condition flag can make it required. Annex XIII 4(d) use data (charging cycles, negative events, temperature history, state of charge) is expected once the battery is in service and never blocks publishing.

  3. Then fall back to required. The map is keyed ONLY by the three in-scope categories, so skipping step 1 falls through to required and invents an obligation the Regulation does not impose. Note also that EV and LMT report state-of-health through MUTUALLY EXCLUSIVE field sets — an EV battery must leave the remaining-capacity cluster empty and an LMT battery must leave stateOfCertifiedEnergy empty, so no single battery ever fills every field.

NameRequiredDescriptionDefault
argsNoArguments for the chosen action; `category` is required for get, ignored for list.
actionYesList all DPP category templates, or get one template by category.

Output Schema

NameRequiredDescription
idNoThe resource's TracePass id, when the response is a single entity.
pageNoCurrent page number (list actions).
errorNoMachine-readable error code, when the API rejected the request.
itemsNoThe page of results, when the action is a list.
limitNoPage size (list actions).
totalNoTotal matching records across all pages (list actions).
resultNoWraps a non-object response body (e.g. a QR code string).
messageNoHuman-readable error or status detail, when present.
totalPagesNoTotal number of pages (list actions).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare read-only/idempotent/non-destructive, yet the description goes far beyond them: it discloses that required-ness is scoped by battery category, that out-of-scope chemistries owe no fields, the precedence order (scope → requiredBy → required), that Annex XIII use data never blocks publishing, and that EV/LMT health fields are mutually exclusive. It even flags the specific failure mode ('skipping step 1 ... invents an obligation').

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?

Front-loaded with a one-line purpose, then a tight bulleted action list before the deep-dive. The BATTERY block is long and dense, but every sentence prevents a concrete error (false obligations, contradictory field sets), so the length is largely earned rather than padded.

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?

An output schema exists and the description still summarizes return shapes; for a two-parameter, read-only reference tool with nested return objects this is fully sufficient. The domain traps an agent would otherwise hit (out-of-scope batteries, conditional fields, mutually exclusive clusters) are all pre-empted.

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?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning: it specifies that `args` is empty for list and ignored-for-list/required-for-get for category, and enumerates what each action returns (field count, required count, regulation, dataType, access level, enum options, validation bounds, article/annex). That is more than the schema supplies, though `category` itself is not expanded beyond the enum list.

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+resource ('Discover the regulatory field schema for each DPP category') and enumerates both actions with their arguments, so an agent can distinguish this reference-lookup tool from siblings like tracepass_passport_fields. The 'what a COMPLIANT passport must contain, per the governing EU regulation' clause pins the scope precisely.

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 clear use contexts: 'advise on requirements before creating products/passports' and 'gap-check a draft against the rules.' It does not name a sibling alternative or state when not to use it (e.g., versus tracepass_passport_fields for an actual passport's values), so it falls short of a 5.

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. 7 tool updatesv1.23.2
    • Changedtracepass_epcis4 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_passport_fields4 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_passport_parties4 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_passports6 fields changed
      • removedInput schema / properties / args / properties / flags / additionalProperties / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / args / properties / flags / additionalProperties / type
        Added value: +[
        +  "boolean",
        +  "null"
        +]
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_products4 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_scope10 fields changed
      • removedInput schema / properties / args / properties / lifecycleEvent / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / args / properties / lifecycleEvent / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedInput schema / properties / args / properties / passportId / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / args / properties / passportId / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedInput schema / properties / args / properties / productId / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedInput schema / properties / args / properties / productId / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedtracepass_templates4 fields changed
      • removedOutput schema / properties / error / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / error / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / message / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / message / type
        Added value: +[
        +  "string",
        +  "null"
        +]
  2. 1 tool updatev1.23.1
    • Changedtracepass_passports3 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (a draft, not billed). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE; battery passports need `reason`), each with a _by_serial variant."New value: +"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (a draft, not billed). Lifecycle: place_on_market (battery, published; async EU registry entry — confirm first) | suspend (reversible) | archive (IRREVERSIBLE; battery passports need `reason`), the last two each with a _by_serial variant."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "get_by_serial",
        -  "compliance",
        -  "registry_readiness",
        -  "get_condition_flags",
        -  "get_condition_flags_by_serial",
        -  "set_condition_flags",
        -  "set_condition_flags_by_serial",
        -  "capture_measurements",
        -  "capture_measurements_by_serial",
        -  "list_measurements",
        -  "list_measurements_by_serial",
        -  "latest_measurements",
        -  "latest_measurements_by_serial",
        -  "create",
        -  "suspend",
        -  "suspend_by_serial",
        -  "archive",
        -  "archive_by_serial",
        -  "get_qr",
        -  "get_qr_by_serial",
        -  "list_snapshots",
        -  "get_snapshot"
        -]New value: +[
        +  "list",
        +  "get",
        +  "get_by_serial",
        +  "compliance",
        +  "registry_readiness",
        +  "place_on_market",
        +  "get_condition_flags",
        +  "get_condition_flags_by_serial",
        +  "set_condition_flags",
        +  "set_condition_flags_by_serial",
        +  "capture_measurements",
        +  "capture_measurements_by_serial",
        +  "list_measurements",
        +  "list_measurements_by_serial",
        +  "latest_measurements",
        +  "latest_measurements_by_serial",
        +  "create",
        +  "suspend",
        +  "suspend_by_serial",
        +  "archive",
        +  "archive_by_serial",
        +  "get_qr",
        +  "get_qr_by_serial",
        +  "list_snapshots",
        +  "get_snapshot"
        +]
      • changedInput schema / properties / args / properties / id / description
        Previous value: -"Passport id. Required for get/compliance/suspend/archive/get_qr (the by-id actions)."New value: +"Passport id. Required for get/compliance/place_on_market/suspend/archive/get_qr (the by-id actions)."
  3. 2 tool updatesv1.22.0
    • Changedtracepass_passport_parties4 fields changed
      • addedInput schema / properties / args / properties / email
        Added value: +{
        +  "description": "Company contact e-mail, not a person's (set, optional). Public.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / postalAddress
        Added value: +{
        +  "description": "Postal address with a single contact point, one line, max 500 chars (set, optional). Public.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / tradeName
        Added value: +{
        +  "description": "Registered trade name or registered trade mark, max 200 chars (set, optional). Public.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / url
        Added value: +{
        +  "description": "Organisation web address (set, optional).",
        +  "type": "string"
        +}
    • Changedtracepass_passports3 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (BILLABLE). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."New value: +"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (a draft, not billed). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE; battery passports need `reason`), each with a _by_serial variant."
      • removedInput schema / properties / args / properties / confirmOverage
        Removed value: -{
        -  "description": "Set true to accept per-passport overage charges when over the plan quota (402). Applies to create.",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / args / properties / reason
        Added value: +{
        +  "description": "archive / archive_by_serial: Required for battery passports: why the passport ends. A battery passport ends only when the battery has been recycled, so the choices are recycled, never placed on the market or put into service, or a duplicate or erroneous record.",
        +  "enum": [
        +    "recycled",
        +    "never_placed",
        +    "duplicate_or_error"
        +  ],
        +  "type": "string"
        +}
  4. 7 tool updatesv1.19.1
    • Changedtracepass_epcis4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
    • Changedtracepass_passport_fields4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
    • Changedtracepass_passport_parties4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
    • Changedtracepass_passports4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
    • Changedtracepass_products4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
    • Addedtracepass_scope
    • Changedtracepass_templates4 fields changed
      • addedOutput schema / properties / error / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / error / type
        Removed value: -"string"
      • addedOutput schema / properties / message / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • removedOutput schema / properties / message / type
        Removed value: -"string"
  5. 1 tool updatev1.17.0
    • Changedtracepass_passport_fields1 field changed
      • addedInput schema / properties / args / properties / source
        Added value: +{
        +  "description": "Where the value came from: \"manual\" (default — the user's statement) or \"ai_suggested\" (you found it; it goes to human review).",
        +  "enum": [
        +    "manual",
        +    "ai_suggested"
        +  ],
        +  "type": "string"
        +}
  6. 1 tool updatev1.16.2
    • Changedtracepass_passports8 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot. Writes: set_condition_flags | set_condition_flags_by_serial | create (BILLABLE). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."New value: +"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot | list_measurements(_by_serial) | latest_measurements(_by_serial). Writes: set_condition_flags | set_condition_flags_by_serial | capture_measurements(_by_serial) | create (BILLABLE). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "get_by_serial",
        -  "compliance",
        -  "registry_readiness",
        -  "get_condition_flags",
        -  "get_condition_flags_by_serial",
        -  "set_condition_flags",
        -  "set_condition_flags_by_serial",
        -  "create",
        -  "suspend",
        -  "suspend_by_serial",
        -  "archive",
        -  "archive_by_serial",
        -  "get_qr",
        -  "get_qr_by_serial",
        -  "list_snapshots",
        -  "get_snapshot"
        -]New value: +[
        +  "list",
        +  "get",
        +  "get_by_serial",
        +  "compliance",
        +  "registry_readiness",
        +  "get_condition_flags",
        +  "get_condition_flags_by_serial",
        +  "set_condition_flags",
        +  "set_condition_flags_by_serial",
        +  "capture_measurements",
        +  "capture_measurements_by_serial",
        +  "list_measurements",
        +  "list_measurements_by_serial",
        +  "latest_measurements",
        +  "latest_measurements_by_serial",
        +  "create",
        +  "suspend",
        +  "suspend_by_serial",
        +  "archive",
        +  "archive_by_serial",
        +  "get_qr",
        +  "get_qr_by_serial",
        +  "list_snapshots",
        +  "get_snapshot"
        +]
      • addedInput schema / properties / args / properties / cursor
        Added value: +{
        +  "description": "list_measurements(_by_serial): nextCursor from the previous page.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / fieldKey
        Added value: +{
        +  "description": "list_measurements(_by_serial): only this field key.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / from
        Added value: +{
        +  "description": "list_measurements(_by_serial): measuredAt from (ISO 8601).",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / lineage
        Added value: +{
        +  "description": "create, battery only: link a second-life battery's new passport to the original passport(s) (Art. 77(7)). See the create action.",
        +  "properties": {
        +    "noPredecessorReason": {
        +      "maxLength": 500,
        +      "type": "string"
        +    },
        +    "predecessors": {
        +      "items": {
        +        "properties": {
        +          "identifier": {
        +            "maxLength": 2000,
        +            "type": "string"
        +          },
        +          "internalPassportId": {
        +            "type": "string"
        +          },
        +          "trigger": {
        +            "enum": [
        +              "preparation_for_reuse",
        +              "preparation_for_repurposing",
        +              "repurposing",
        +              "remanufacturing"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "trigger"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 10,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "predecessors"
        +  ],
        +  "type": "object"
        +}
      • addedInput schema / properties / args / properties / measurements
        Added value: +{
        +  "description": "capture_measurements(_by_serial): [{ fieldKey, value, measuredAt, externalId?, unit? }], max 500.",
        +  "items": {
        +    "properties": {
        +      "externalId": {
        +        "type": "string"
        +      },
        +      "fieldKey": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "measuredAt": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "unit": {
        +        "type": "string"
        +      },
        +      "value": {}
        +    },
        +    "required": [
        +      "fieldKey",
        +      "value",
        +      "measuredAt"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / args / properties / to
        Added value: +{
        +  "description": "list_measurements(_by_serial): measuredAt to (ISO 8601).",
        +  "type": "string"
        +}
  7. 2 tool updatesv1.14.1
    • Changedtracepass_passport_parties6 fields changed
      • changedInput schema / properties / args / properties / country / description
        Previous value: -"Party country code (set, optional)."New value: +"ISO 3166-1 alpha-2 country code (set, optional)."
      • addedInput schema / properties / args / properties / facilityIdentifier
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Structured facility identifier per EN 18219 §6.2–6.5. Same four schemes as operatorIdentifier; the gln variant also accepts optional `extension` (GS1 SGLN sub-location). Never fills the top-level gln field. Not set by AI extraction.",
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / args / properties / gln / description
        Previous value: -"GS1 Global Location Number for the party (set, optional)."New value: +"GS1 Global Location Number (13 digits). Strongly recommended for multi-role disambiguation."
      • changedInput schema / properties / args / properties / legacyOperatorId / description
        Previous value: -"Your internal operator id for the party (set, optional)."New value: +"Free-text fallback identifier (VAT, EORI, supplier code). Required when gln and operatorIdentifier are both absent."
      • addedInput schema / properties / args / properties / operatorIdentifier
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Structured operator identifier per EN 18219 §6.2–6.5. Must have `scheme` plus scheme fields. Schemes: iso6523 {icd:\"<4 digits>\", value} | gln {gln:\"<13 digits>\"} | did {did:\"did:<method>:<id>\"} | doi {doi:\"10.<registrant>/<suffix>\"}. scheme gln also fills the top-level gln field; they must match if both are set (400 otherwise). Not set by AI extraction.",
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / args / properties / role / description
        Previous value: -"Economic-operator role, e.g. manufacturer | importer | distributor | authorised_representative (required)."New value: +"Economic-operator role: manufacturer | importer | authorisedRepresentative | distributor | recycler | producerResponsibilityOrg (required)."
    • Changedtracepass_passports11 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_qr | get_qr_by_serial. Lifecycle: create (BILLABLE) | suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."New value: +"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_condition_flags | get_condition_flags_by_serial | get_qr | get_qr_by_serial | list_snapshots | get_snapshot. Writes: set_condition_flags | set_condition_flags_by_serial | create (BILLABLE). Lifecycle: suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "get_by_serial",
        -  "compliance",
        -  "registry_readiness",
        -  "create",
        -  "suspend",
        -  "suspend_by_serial",
        -  "archive",
        -  "archive_by_serial",
        -  "get_qr",
        -  "get_qr_by_serial"
        -]New value: +[
        +  "list",
        +  "get",
        +  "get_by_serial",
        +  "compliance",
        +  "registry_readiness",
        +  "get_condition_flags",
        +  "get_condition_flags_by_serial",
        +  "set_condition_flags",
        +  "set_condition_flags_by_serial",
        +  "create",
        +  "suspend",
        +  "suspend_by_serial",
        +  "archive",
        +  "archive_by_serial",
        +  "get_qr",
        +  "get_qr_by_serial",
        +  "list_snapshots",
        +  "get_snapshot"
        +]
      • addedInput schema / properties / args / properties / at
        Added value: +{
        +  "description": "list_snapshots: ISO 8601 instant — return the snapshot valid then instead of the list.",
        +  "type": "string"
        +}
      • changedInput schema / properties / args / properties / confirmOverage / description
        Previous value: -"Set true to accept a per-passport overage charge when create is over the plan quota (402)."New value: +"Set true to accept per-passport overage charges when over the plan quota (402). Applies to create."
      • addedInput schema / properties / args / properties / flags
        Added value: +{
        +  "additionalProperties": {
        +    "anyOf": [
        +      {
        +        "type": "boolean"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ]
        +  },
        +  "description": "For set_condition_flags / set_condition_flags_by_serial: Record<flagKey, boolean|null>. null clears the flag.",
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / args / properties / gtin / description
        Previous value: -"GTIN disambiguator for *_by_serial actions when a serial isn't unique across GTINs (else 409 ambiguous_serial)."New value: +"For create (legacy): GS1 GTIN. Also used as a disambiguator for *_by_serial actions when a serial isn't unique (else 409 ambiguous_serial)."
      • changedInput schema / properties / args / properties / id / description
        Previous value: -"Passport id. Required for get/compliance/create-result/suspend/archive/get_qr (the by-id actions)."New value: +"Passport id. Required for get/compliance/suspend/archive/get_qr (the by-id actions)."
      • addedInput schema / properties / args / properties / identifier
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "EN 18219 scheme-tagged identifier for create. Must have `scheme` plus scheme-specific fields. Schemes: gs1 {gtin, serialNumber} | iso15459 {issuingAgencyCode, primaryId, serial?} | iec61406 {uri} | did {did, method} | doi {doi, granularity} (granularity: \"model\"|\"batch\"|\"item\" REQUIRED per EN 18219 §5.6.2(b)). Battery passports: gs1 and iso15459 only.",
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • changedInput schema / properties / args / properties / serialNumber / description
        Previous value: -"Serial for the new passport. Required for create."New value: +"Serial for the new passport (create, legacy gs1 path)."
      • addedInput schema / properties / args / properties / snapshotId
        Added value: +{
        +  "description": "Snapshot id. Required for get_snapshot.",
        +  "type": "string"
        +}
      • addedInput schema / properties / args / properties / symbology
        Added value: +{
        +  "description": "get_qr/get_qr_by_serial: qr (default) | datamatrix.",
        +  "type": "string"
        +}
  8. 2 tool updatesv1.8.0
    • Changedtracepass_products1 field changed
      • changedInput schema / properties / args / properties / category / description
        Previous value: -"DPP category for create: battery | textile | electronics | construction | steel | chemicals | packaging | furniture | tyres | jewelry | toys | fmcg."New value: +"DPP category for create: battery | textile | electronics | construction | steel | detergents | paints-coatings | packaging | furniture | tyres | jewelry | toys | fmcg."
    • Changedtracepass_templates1 field changed
      • changedInput schema / properties / args / properties / category / description
        Previous value: -"DPP category to fetch (required for get): battery | textile | electronics | construction | steel | chemicals | packaging | furniture | tyres | jewelry | toys | fmcg."New value: +"DPP category to fetch (required for get): battery | textile | electronics | construction | steel | detergents | paints-coatings | packaging | furniture | tyres | jewelry | toys | fmcg."
  9. 6 tool updatesv1.7.3
    • Changedtracepass_epcis7 fields changed
      • addedInput schema / properties / action / description
        Added value: +"EPCIS 2.0: export a passport's events (export | export_by_serial), capture new events, poll a capture job, or query events."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "export",
        -  "capture",
        -  "capture_job",
        -  "query"
        -]New value: +[
        +  "export",
        +  "export_by_serial",
        +  "capture",
        +  "capture_job",
        +  "query"
        +]
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description."New value: +"Arguments for the chosen action; required fields depend on `action`."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "events": {
        +    "description": "EPCIS 2.0 event payload (an EPCISDocument or event list). Required for capture."
        +  },
        +  "gtin": {
        +    "description": "GTIN disambiguator for export_by_serial when the serial isn't unique (else 409).",
        +    "type": "string"
        +  },
        +  "id": {
        +    "description": "Passport id. Required for export.",
        +    "type": "string"
        +  },
        +  "jobId": {
        +    "description": "Capture job id to poll. Required for capture_job.",
        +    "type": "string"
        +  },
        +  "params": {
        +    "additionalProperties": {
        +      "type": "string"
        +    },
        +    "description": "EPCIS query parameters as key→value strings (query, optional).",
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "serial": {
        +    "description": "Your serial. Required for export_by_serial.",
        +    "type": "string"
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedtracepass_passport_fields7 fields changed
      • addedInput schema / properties / action / description
        Added value: +"Update one passport field, addressed by passport id (update) or by your serial (update_by_serial)."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "update"
        -]New value: +[
        +  "update",
        +  "update_by_serial"
        +]
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description."New value: +"Arguments for the chosen action; required fields depend on `action`."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "fieldKey": {
        +    "description": "The field key to set (required).",
        +    "type": "string"
        +  },
        +  "gtin": {
        +    "description": "GTIN disambiguator for update_by_serial when the serial isn't unique (else 409).",
        +    "type": "string"
        +  },
        +  "id": {
        +    "description": "Passport id. Required for update.",
        +    "type": "string"
        +  },
        +  "serial": {
        +    "description": "Your serial. Required for update_by_serial.",
        +    "type": "string"
        +  },
        +  "value": {
        +    "description": "The new value for the field (required). Type depends on the field's dataType."
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedtracepass_passport_parties6 fields changed
      • addedInput schema / properties / action / description
        Added value: +"Set (add/replace) or remove an economic-operator party on a passport by its role."
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description."New value: +"Arguments for the chosen action; required fields depend on `action`."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "country": {
        +    "description": "Party country code (set, optional).",
        +    "type": "string"
        +  },
        +  "gln": {
        +    "description": "GS1 Global Location Number for the party (set, optional).",
        +    "type": "string"
        +  },
        +  "id": {
        +    "description": "Passport id (required).",
        +    "type": "string"
        +  },
        +  "legacyOperatorId": {
        +    "description": "Your internal operator id for the party (set, optional).",
        +    "type": "string"
        +  },
        +  "legalName": {
        +    "description": "Party legal name. Required for set.",
        +    "type": "string"
        +  },
        +  "role": {
        +    "description": "Economic-operator role, e.g. manufacturer | importer | distributor | authorised_representative (required).",
        +    "type": "string"
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedtracepass_passports7 fields changed
      • addedInput schema / properties / action / description
        Added value: +"Which passport operation to run. Reads: list | get | get_by_serial | compliance | registry_readiness | get_qr | get_qr_by_serial. Lifecycle: create (BILLABLE) | suspend (reversible) | archive (IRREVERSIBLE), each with a _by_serial variant."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "get_by_serial",
        -  "create",
        -  "suspend",
        -  "archive",
        -  "get_qr"
        -]New value: +[
        +  "list",
        +  "get",
        +  "get_by_serial",
        +  "compliance",
        +  "registry_readiness",
        +  "create",
        +  "suspend",
        +  "suspend_by_serial",
        +  "archive",
        +  "archive_by_serial",
        +  "get_qr",
        +  "get_qr_by_serial"
        +]
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description for each action's shape."New value: +"Arguments for the chosen action; required fields depend on `action` (see each action above)."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "confirmOverage": {
        +    "description": "Set true to accept a per-passport overage charge when create is over the plan quota (402).",
        +    "type": "boolean"
        +  },
        +  "format": {
        +    "description": "get/get_by_serial: summary|full. get_qr/get_qr_by_serial: svg|png.",
        +    "type": "string"
        +  },
        +  "gtin": {
        +    "description": "GTIN disambiguator for *_by_serial actions when a serial isn't unique across GTINs (else 409 ambiguous_serial).",
        +    "type": "string"
        +  },
        +  "id": {
        +    "description": "Passport id. Required for get/compliance/create-result/suspend/archive/get_qr (the by-id actions).",
        +    "type": "string"
        +  },
        +  "lang": {
        +    "description": "Resolve field values to one of the 24 EU locales server-side (get/get_by_serial).",
        +    "type": "string"
        +  },
        +  "limit": {
        +    "description": "Page size for list, max 100.",
        +    "type": "number"
        +  },
        +  "page": {
        +    "description": "Page number for list (1-based).",
        +    "type": "number"
        +  },
        +  "productId": {
        +    "description": "Parent product id. Required for create.",
        +    "type": "string"
        +  },
        +  "search": {
        +    "description": "Filter list by a search term.",
        +    "type": "string"
        +  },
        +  "serial": {
        +    "description": "Your own serial number. Required for the *_by_serial actions.",
        +    "type": "string"
        +  },
        +  "serialNumber": {
        +    "description": "Serial for the new passport. Required for create.",
        +    "type": "string"
        +  },
        +  "status": {
        +    "description": "Filter list by status: draft|in_review|approved|published|suspended|expired|archived.",
        +    "type": "string"
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedtracepass_products7 fields changed
      • addedInput schema / properties / action / description
        Added value: +"Which product operation to run: list | get | create | create_batch | update | archive."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "create",
        -  "update"
        -]New value: +[
        +  "list",
        +  "get",
        +  "create",
        +  "create_batch",
        +  "update",
        +  "archive"
        +]
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description for each action's shape."New value: +"Arguments for the chosen action; required fields depend on `action` (see each action above)."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "category": {
        +    "description": "DPP category for create: battery | textile | electronics | construction | steel | chemicals | packaging | furniture | tyres | jewelry | toys | fmcg.",
        +    "type": "string"
        +  },
        +  "description": {
        +    "description": "Free-text product description (create/update).",
        +    "type": "string"
        +  },
        +  "id": {
        +    "description": "Product id. Required for get and update.",
        +    "type": "string"
        +  },
        +  "limit": {
        +    "description": "Page size for list, max 100.",
        +    "type": "number"
        +  },
        +  "model": {
        +    "description": "Manufacturer model / SKU. Required for create; optional on update.",
        +    "type": "string"
        +  },
        +  "name": {
        +    "description": "Product name. Required for create; optional on update.",
        +    "type": "string"
        +  },
        +  "page": {
        +    "description": "Page number for list (1-based).",
        +    "type": "number"
        +  },
        +  "products": {
        +    "description": "Products to create for create_batch: [{ name, model, category, description? }], max 100.",
        +    "items": {
        +      "additionalProperties": {},
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "search": {
        +    "description": "Filter list by a search term.",
        +    "type": "string"
        +  },
        +  "status": {
        +    "description": "Filter list by product status.",
        +    "type": "string"
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedtracepass_templates6 fields changed
      • addedInput schema / properties / action / description
        Added value: +"List all DPP category templates, or get one template by category."
      • removedInput schema / properties / args / additionalProperties
        Removed value: -{}
      • changedInput schema / properties / args / description
        Previous value: -"Action-specific arguments — see the description for each action's shape."New value: +"Arguments for the chosen action; `category` is required for get, ignored for list."
      • addedInput schema / properties / args / properties
        Added value: +{
        +  "category": {
        +    "description": "DPP category to fetch (required for get): battery | textile | electronics | construction | steel | chemicals | packaging | furniture | tyres | jewelry | toys | fmcg.",
        +    "type": "string"
        +  }
        +}
      • removedInput schema / properties / args / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "error": {
        +      "description": "Machine-readable error code, when the API rejected the request.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "The resource's TracePass id, when the response is a single entity.",
        +      "type": "string"
        +    },
        +    "items": {
        +      "description": "The page of results, when the action is a list.",
        +      "items": {},
        +      "type": "array"
        +    },
        +    "limit": {
        +      "description": "Page size (list actions).",
        +      "type": "number"
        +    },
        +    "message": {
        +      "description": "Human-readable error or status detail, when present.",
        +      "type": "string"
        +    },
        +    "page": {
        +      "description": "Current page number (list actions).",
        +      "type": "number"
        +    },
        +    "result": {
        +      "description": "Wraps a non-object response body (e.g. a QR code string)."
        +    },
        +    "total": {
        +      "description": "Total matching records across all pages (list actions).",
        +      "type": "number"
        +    },
        +    "totalPages": {
        +      "description": "Total number of pages (list actions).",
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
  10. 6 tool updatesv1.1.4
    • First observedtracepass_epcis
    • First observedtracepass_passport_fields
    • First observedtracepass_passport_parties
    • First observedtracepass_passports
    • First observedtracepass_products
    • First observedtracepass_templates

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation4/5

The seven top-level tools map to clearly distinct domains: product catalogue, passport lifecycle, passport fields, economic-operator parties, EPCIS events, template schemas, and legal scope. Boundary risk is mostly inside tracepass_passports, whose many paired *_by_serial actions overlap conceptually with their by-id siblings, though the descriptions explicitly disambiguate (serial uniqueness, 409 ambiguous_serial, GTIN disambiguation).

Naming Consistency4/5

All tools share the tracepass_ prefix and a consistent resource-noun layout, with actions expressed uniformly as verbs via the action parameter. Minor deviations: plural 'products'/'passports' vs singular 'passport_fields'/'passport_parties', and parties uses set/remove while fields uses update, but the pattern is still highly predictable.

Tool Count4/5

Seven top-level tools is well within the ideal 3-15 range for a DPP platform and each tool earns its place. However tracepass_passports concentrates roughly 25 actions (list/get/QR/snapshots/condition flags/measurements/compliance/registry/place_on_market plus many *_by_serial variants), making that one tool disproportionately heavy.

Completeness4/5

The surface covers products, passport create/read/lifecycle, field updates, parties, EPCIS capture/query/export, templates, and scope checking, which is broad lifecycle coverage. Gaps remain: publishing is explicitly out of band (dashboard only), products have archive but no unarchive, and parties offer set/remove but no dedicated read action.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers