Connect the MCP server
By the end of this page, you will know what the SealTrust MCP server allows an assistant to do, how to connect it to your client, which identifier to pass it, and what each of its seven tools returns. You will also know how to connect the admin server, which prepares a brand's catalog without ever publishing, add it in Claude with your account, and end that connection.
On this page
- 1. The scope, before anything else
- 2. Connect the server
- Nothing to install: the hosted address
- On your machine: the npm package
- Declare the server in a client
- The available settings
- 3. Know which identifier you have
- 4. The seven tools
- verify_product
- get_passport
- get_passport_proof
- get_product_history
- get_certificate
- resolve_gs1
- verify_credential
- 5. Reading responses and errors
- 6. The call limits
- On the hosted address
- On the API, for the npm package
- The admin server: the assistant prepares, a person publishes
- What it does, and what it refuses
- The hosted address: add it in Claude
- End a connection
- On your machine: the key, one per brand
- Connect it
- The typical path
- What protects you
- What can stop you
The MCP server gives a conversational assistant the right to query the SealTrust
public API, read only. MCP, for Model Context Protocol, is the standardized
protocol through which an assistant calls external tools. It comes in two forms,
with the same seven tools: an address hosted by SealTrust,
https://mcp.sealtrust.io/mcp, to paste into Claude or ChatGPT, and a small
program that you run on your own machine with npx. By the end of this page,
you will know how to connect either one, choose the identifier to pass and call
the seven tools.
The path has four steps: check that the scope matches your need, connect the server to your client, learn which identifier you have at hand, call the tools.
Do you want an assistant to prepare your brand's catalog, not only read published passports? That is the admin server's job, described further down in its own part.
#1. The scope, before anything else
The server issues only GET requests, to public endpoints of
https://api.sealtrust.io. It sends no API key and accepts none. None of its
tools creates, modifies or deletes anything.
Direct consequence: the server sees exactly what an anonymous visitor sees when
opening a passport in their browser. The ESPR regulation distinguishes several
audiences: the public, consumers, value chain professionals and market
surveillance authorities. SealTrust applies that distinction with six access
levels: public, end_user, repairer, recycler, upstream and
authority. These values are SealTrust's own. The regulation, for its part,
names audiences. The MCP server reads the public level and that level only.
Fields reserved for professionals or authorities cannot be reached through this
path.
What the server announces to your client when the connection opens: its name,
sealtrust, its version, and a sentence of instructions reminding the assistant
that all data is public and that no tool modifies anything.
#2. Connect the server
#Nothing to install: the hosted address
The address https://mcp.sealtrust.io/mcp serves the same seven tools, with the
same descriptions, as the program described below. It needs no account and no
key. In Claude, add it as a custom connector. In ChatGPT, turn on developer mode
then create a connector with this address. The exact steps, screen by screen,
are in Claude and ChatGPT in 30 seconds.
With Claude Code, without Node.js:
claude mcp add --transport http sealtrust https://mcp.sealtrust.io/mcpThe transport is the Streamable HTTP of the MCP specification, without a
session: each message is an independent POST request. A GET or a DELETE
on the address answers 405. The limits of this address are in point 6.
#On your machine: the npm package
You need Node.js version 18 or later. The package is called
@sealtrust-io/mcp-server and the latest published version is 0.4.0.
You can launch it directly, which serves to check that it starts.
npx @sealtrust-io/mcp-serverThe server communicates through its standard input and output. A startup line goes to the error output and indicates the version as well as the API address in use. Standard output is reserved for the dialogue with the client, so nothing else is written there.
#Declare the server in a client
An MCP client is configured with a command and its arguments. The block below is the form expected by desktop clients, to be placed in their configuration file.
{
"mcpServers": {
"sealtrust": {
"command": "npx",
"args": ["-y", "@sealtrust-io/mcp-server"]
}
}
}On the command line with Claude Code, the same declaration is written as follows.
claude mcp add sealtrust -- npx -y @sealtrust-io/mcp-serverRestart the client after modifying its configuration. The seven tools then appear in its list of available tools.
#The available settings
Three environment variables change the behavior of the program run with npx.
In practice, only the first two are of use to you.
| Variable | Default value | Effect |
|---|---|---|
SEALTRUST_API_URL | https://api.sealtrust.io | The address of the API being queried. Trailing slashes are stripped. |
SEALTRUST_TIMEOUT_MS | 15000 | The maximum duration of a call, in milliseconds. A value that is not a strictly positive number is ignored, and the default value applies. |
SEALTRUST_PUBLIC_API_URL | the value of SEALTRUST_API_URL | The API address written into the links a tool returns, such as gs1_digital_link. It only matters when the server reaches the API through a private address. |
The timeout covers the full round trip, headers and response body included. Going over it returns an explicit network error, never a silent hang.
These two variables go in your client's configuration, under the env key. The
block below is complete and can be copied as is. It carries a 30 second timeout.
{
"mcpServers": {
"sealtrust": {
"command": "npx",
"args": ["-y", "@sealtrust-io/mcp-server"],
"env": {
"SEALTRUST_TIMEOUT_MS": "30000"
}
}
}
}#3. Know which identifier you have
Six tools out of seven take a product identifier. Four forms exist, and they are not accepted everywhere.
| Form | What it looks like | Where you find it |
|---|---|---|
| Serial number | 12 characters, digits and uppercase letters, for example EXEMP1E00000 | This is the only identifier readable on a product. The printed QR carries it. Someone who has scanned or copied a label has that one. |
Identifier hash (uid_hash) | 0x followed by 64 hexadecimal characters | Returned by our own responses. This is the product's internal identifier. It comes from the NFC chip when the product carries one. SealTrust draws it at random when the product is identified by QR alone. |
| Token identifier | A string of digits | The identifier of the on-chain token, returned under the name token_id. |
| Certificate number | Starts with ST-CERT- | On the certificate of authenticity. Accepted by verify_product and get_certificate only. |
The serial number alphabet excludes the letters I, L, O and U, so that a person
copying a label does not mistake a letter for a digit. The MCP server passes the
number along exactly as it is given, without rewriting a single character. It is
the API that puts the number back in uppercase and that brings ambiguous
characters back to their canonical form: I and L are worth 1, O is worth
0.
Two tools also take a GTIN, the article code with 8, 12, 13 or 14 digits. A GTIN designates a model. It designates no particular item.
#4. The seven tools
#verify_product
Answers the question "is this number registered, and is its certificate in force". It never says that the object in hand is the original: a QR code or a serial can be copied, only a chip read proves it. The tool chains two calls: resolving the identifier, then reading the certificate.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | Serial number, identifier hash, token identifier or certificate number. |
The response carries a status field that takes five values.
| Value | What it means |
|---|---|
registered | The number is registered and an active certificate of authenticity is attached to it. The published version 0.4.0 names this value authentic; it becomes registered from version 0.5.0. |
revoked | The certificate has been revoked. The product is to be treated as suspect. |
expired | The certificate has passed its end date. |
found_no_certificate | The product exists in the registry and no active certificate is attached to it. |
unknown | No trace of this identifier. |
Coming with them: a plain text message field, a product block carrying the
product name, the brand name, the category, the token identifier, the identifier
hash, the contract address, the mint transaction and the creation date, a
certificate block or the null value, a has_published_passport boolean, and an
anchored_on_base boolean.
anchored_on_base is true when an anchor exists, whichever one it is: the one
for the product batch, or the one for the passport content. The two are
independent. A passport can be anchored while its batch has not been, and the
other way around. To find out which of the two, and with which transaction, call
get_passport_proof.
Expect this boolean to be false most of the time. Anchoring is an operation that
SealTrust triggers by hand. An anchoring request coming from a brand account is
refused. Minting a product does not anchor it, and publishing a passport does not
anchor it either. Most products are never anchored. So an anchored_on_base set
to false says nothing against the product, and your assistant must never present
it as a suspicion.
#get_passport
Returns the published digital passport, at the public access level.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | Serial number, identifier hash or token identifier. A certificate number is not accepted here. |
format | string | no | json by default, or jsonld for a representation in Schema.org and GS1 vocabulary. Any other value is refused before the network call. |
The response in the default format carries the passport version, the published
content under the data field, the SHA-256 hash of that content under
data_hash, the name of the product and of the brand, the GTIN and the product's
GS1 Digital Link.
The two fields that point to the IPFS copy always hold the null value on this
path. They are reserved for authenticated access levels. The link to the
immutable copy, when it is published, appears in the response of
get_passport_proof.
#get_passport_proof
Returns the public proofs that make it possible to verify a passport without trusting us.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | no | The item you want the proof for. |
gtin | string | no | The model you want the proof for, at reference level. |
You must supply exactly one of the two. Neither of them, or both at once, gives an immediate refusal with a message that explains the difference. The two parameters do not designate the same thing: the proof of an item dates the object, the proof of a reference dates the document.
The response contains the content hash, the link to the IPFS copy when it is
published, a seal block that says whether the version is sealed and whether its
content still matches what was sealed, the issuance state of the verifiable
credential, and the number of successful physical verifications. A missing proof
is absent from the response, with no empty field.
A reference level passport, the one obtained with gtin, legitimately carries
neither an anchor block nor a verification count. It is tied to no physical
item. Its proof is the anchoring of its own content, which dates the document.
The response then carries level: "model" and the normalized GTIN.
#get_product_history
Returns the history of a product: ownership movements and authentication scans,
gathered into a single timeline, from the most recent to the oldest. The first
element of timeline is the most recent event.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | Serial number, identifier hash or token identifier. |
Each entry carries a type field that is verify for a scan or transfer for
an ownership movement, a timestamp, the token identifier and the identifier hash.
The rest depends on the type. A verify entry carries a validity indicator and
no party label. A transfer entry carries two display ready labels, for the
party giving up and the party receiving, and no validity indicator.
For an anonymous caller, and the MCP server is one, identities are masked: email addresses are anonymized and raw wallet addresses are not returned.
#get_certificate
Returns the public certificate of authenticity of a product.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | Serial number, identifier hash, token identifier or certificate number. |
The response carries the certificate number, its state, its issuance date, its end date when there is one, the name of the issuer, the name of the product and that of the brand, as well as the custom fields recorded at issuance, returned as is. Everything written there is public.
#resolve_gs1
Starts from a GS1 Digital Link and returns the passport it designates.
| Parameter | Type | Required | Description |
|---|---|---|---|
gtin | string | yes | The article code of the model. |
serial | string | no | The serial number printed on the item. Omit it to target the model. |
The presence of the serial number changes what the link designates. With it, the
link /01/{gtin}/21/{serial} designates a precise item and the response carries
level: "item". Without it, the link /01/{gtin} designates the article class
and returns the reference level passport, the one shared by every item of the
model, with level: "model". Model codes already printed are served at that
second level. An empty string in serial is read as an absence.
The response also carries the reconstructed link, the address the resolution redirects to, the identifier retained, and the public passport when there is one.
Without a published reference passport, /01/{gtin} answers 404 and the tool
returns found: false with the message "Unknown GS1 Digital Link". The result
resolved: true accompanied by a null passport only happens when you supply a
serial and that item has no published passport.
The serial number expected here is indeed the one printed on the product. The on-chain token identifier is not suitable in this place.
#verify_credential
Verifies the signature of the passport's verifiable credential, in SD-JWT-VC
format, against the key published by the issuing brand in the form did:web.
| Parameter | Type | Required | Description |
|---|---|---|---|
identifier | string | one of the two | Serial number, identifier hash or token identifier, for the passport of an item. |
gtin | string | one of the two | The GTIN of a model, for the passport of that model. |
lot | string | no | With gtin only: the lot number as printed, for the passport of that lot. |
Pass identifier or gtin, never both. The passport of a model or a lot is
bound to no item, and a brand on the Compliance offer registers none: gtin is
then the only way to reach its credential. These two parameters come with
version 0.6.0 of the server, not yet published: the published version 0.4.0
takes identifier only.
The response carries verified, the issuer's decentralized identifier, the type
of the credential, the version of the signing key, the access level applied, an
error field holding verification_failed in case of failure, and the content
of the credential when the signature is valid.
#5. Reading responses and errors
The server separates three situations, and that separation matters for an assistant reasoning on the result.
| Situation | What the server returns | What to conclude from it |
|---|---|---|
| Product, passport or credential untraceable | A normal result carrying found: false and the API message, or status: "unknown" for verify_product | The question got an answer. Nothing broke. |
| API error response other than a 404 | A tool error whose message reads SealTrust API error (, the HTTP code, ): , then the detail returned by the API. There is no space before the colon. | The API answered and refused. The code says why. |
| API unreachable, timeout exceeded, DNS, connection refused | A tool error starting with Network error | No information about the product. Conclude nothing about its authenticity. |
A malformed argument is refused before any network call: an empty identifier, a
format that is neither json nor jsonld, or the absence of a choice between
identifier and gtin on the proof.
#6. The call limits
#On the hosted address
The address https://mcp.sealtrust.io/mcp applies three limits, all over a 60
second window.
| Limit | Value | What is counted |
|---|---|---|
| Per IP address | 300 requests per minute | Every request, tools or not. Beyond it, the answer is 429 before the server is reached. |
| Per client | 120 tool calls per minute | Tool calls only. Listing the tools does not count. |
| For all users together | 480 reads per minute on each public read family, 48 on the GS1 resolution | The calls the hosted server makes to the API. |
The third limit exists because the hosted server reaches the API from a single
address, its own. The API counts per address: every user of the hosted address
therefore shares the API limits of the next table, and the server keeps 80 % of
them so that they are never refused to it. Beyond that, the tool returns an
error that starts with SealTrust API error (429) and says in how many seconds
to retry, without having called the API.
Claude and ChatGPT call from their vendor's servers. Many users therefore share a few addresses, and a 429 can come from a user other than you. If you meet it often, run the npm package on your machine: it calls the API from your own address.
#On the API, for the npm package
Public endpoints are capped per calling IP address, over a 60 second window. The path families that have a limit of their own each keep their own counter. The others fall under a general counter, shared by all routes without a dedicated limit.
| Tool | Path called | Limit |
|---|---|---|
verify_product | resolution, then certificate | 600 per minute on each of the two |
get_passport, get_passport_proof, verify_credential | passport | 600 per minute |
get_certificate | certificate | 600 per minute |
get_product_history | timeline | 600 per minute |
resolve_gs1 | GS1 resolution, then passport | 60 per minute on the GS1 resolution, then 600 per minute on the passport |
Two tools consume two calls instead of one. verify_product queries the
resolution then the certificate. resolve_gs1 reads the resolver's redirect
without following it, then requests the passport directly. Count them as two.
Going over the limit returns a 429 response, which the server surfaces as a tool
error. One case is an exception. On verify_product, only the first call
surfaces a 429. Going over the limit on the certificate read is logged to the
error output and the tool answers anyway, with the summarized certificate that
the resolution already carries.
#The admin server: the assistant prepares, a person publishes
A second server, @sealtrust-io/mcp-admin, serves one brand. With it, an
assistant prepares your catalog: it creates models and batches, opens
passport drafts, completes them, and shows you what is still missing. It never
publishes. Publishing seals a version for good, so a person reviews the draft
and publishes it in the console.
It comes in two forms, with the same tools and the same refusals: a hosted
address, https://mcp.sealtrust.io/admin/mcp, that you add as a connector in
Claude and where you sign in with your console account; and a program run on
your own machine with your brand's key. The address
https://mcp.sealtrust.io/mcp stays the public, read-only server's.
#What it does, and what it refuses
| It can | Tools |
|---|---|
| Read models, batches and passports | list_product_models, get_product_model, list_batches, get_batch, list_passports, get_passport_draft |
| Read passport templates | list_dpp_templates, get_dpp_template |
| Say what is missing and what each audience will see | get_readiness, preview_passport |
| Create and complete models and batches | create_product_model, update_product_model, create_batch |
| Open and complete a passport draft, for a model or a batch | create_passport_draft, update_passport_draft |
It refuses, with a message pointing to the console: publishing a passport,
anchoring or minting on chain, transferring, issuing purchase codes, deleting
anything, managing keys, the team, billing or access rules.
update_passport_draft also refuses a sealed version: a correction starts with
a new draft. Item passport drafts are prepared in the console.
#The hosted address: add it in Claude
Nothing to install, and no key to copy: you sign in with your console account, and you choose what the assistant is allowed to do.
- In Claude, open Settings, then Connectors, then "Add custom connector". Give
it a name, for example
SealTrust admin, and the addresshttps://mcp.sealtrust.io/admin/mcp. - Click "Connect". Claude opens the SealTrust console. Sign in with your account, two-factor authentication included if it is on.
- The "Connect an AI assistant" page shows who asks for access and the address you will be sent back to, which must be Claude's. Choose ONE brand among those you administer. "Read the catalogue" is always granted. "Prepare drafts" is never ticked in advance: tick it yourself if the assistant must also create and complete.
- Click "Allow". Claude takes over and the tools appear. Without "Prepare drafts", the five writing tools do not appear, and the API would refuse them anyway.
| Point | Rule |
|---|---|
| Brand | One only, chosen when you allow. No tool takes a brand as an argument. |
| Token lifetime | 30 minutes. Claude renews it on its own, without asking you again. |
| Connection lifetime | 90 days at most. Then Claude asks you to sign in again. |
| SealTrust team account | Refused: sign in with an account of the brand. |
| Plan | The brand's plan must include the partner API, as for a key. |
| Limits | 60 tool calls a minute per connection, 30 API calls a minute per connection. |
| Number of connections | 10 at most per person, 25 at most per brand. Beyond, the console asks you to end a connection first. |
| Password | Changing or resetting it ends all your assistant connections. |
For Claude Code, the same address is added as follows, and you sign in in your browser.
claude mcp add --transport http sealtrust-admin https://mcp.sealtrust.io/admin/mcp#End a connection
In the console, open Settings, then Developers: the "AI assistant connections" card lists the connections of your brands, yours and your colleagues', with the brand, the person who allowed it, the date of last use and the end date. "End this connection" cuts the access at the assistant's next request.
A connection also ends on its own when the person who allowed it loses their rights on the brand or no longer has an active account. Removing the connector in Claude does not always revoke the access: end the connection in the console.
#On your machine: the key, one per brand
The server calls the partner API with an API key of your brand. Create it in
the console, Settings then Developers, with the catalog:read and
catalog:write scopes. Create a key for this use only: you can then revoke it
without cutting your other integrations.
The key goes in the server's environment, never in the conversation. No tool takes a brand or a key as an argument. On the first call, the server asks the API which brand the key acts for. It refuses to work if the key acts for several brands: a reseller key does not fit, create one key per client brand.
| Variable | Required | Effect |
|---|---|---|
SEALTRUST_ADMIN_API_KEY | yes | The brand's API key. |
SEALTRUST_BRAND_CODE | no | The code of the expected brand. If the key belongs to another brand, the server refuses to work. |
SEALTRUST_MAX_CALLS_PER_MINUTE | no | API calls per minute, 30 by default, 120 at most. Beyond it, the tool answers a clear error instead of insisting. |
SEALTRUST_API_URL | no | The API address, in https://. |
#Connect it
SealTrust hands you the package: it is not published on npm. Give your client
the path of the package's dist/index.js file.
{
"mcpServers": {
"sealtrust-admin": {
"command": "node",
"args": ["/path/to/mcp-admin/dist/index.js"],
"env": {
"SEALTRUST_ADMIN_API_KEY": "st_live_your_key",
"SEALTRUST_BRAND_CODE": "7K3QXW9M2A"
}
}
}
}With Claude Code, the same declaration reads as follows.
claude mcp add sealtrust-admin \
-e SEALTRUST_ADMIN_API_KEY=st_live_your_key \
-e SEALTRUST_BRAND_CODE=7K3QXW9M2A \
-- node /path/to/mcp-admin/dist/index.js#The typical path
- Ask the assistant to start from a template:
list_dpp_templates, thencreate_passport_draftwithtemplate. - Give it your information. It completes the draft with
update_passport_draft. It must invent neither a figure nor a regulatory declaration: what you do not give it stays empty. - It reads
get_readinessto tell you what is missing, thenpreview_passportto show you what each audience will see. - You review and publish in the console, Passports page.
#What protects you
- Every call goes through the API, with your key. The brand's activity log records each write under the key's name, and the API's limits apply.
- The server only calls the catalog endpoints of your brand. Any other address is refused before sending.
- Everything the API returns is presented to the assistant as untrusted data. A text written in a passport triggers no tool, even if it reads like an order.
- The key appears neither in the server's logs nor in its answers.
- On the hosted address, every authorization, every use of a token and every end of a connection is written to the activity log, under the name of the person who allowed the connection. SealTrust keeps only a fingerprint of the tokens, never the tokens themselves.
- A token is valid only for SealTrust's admin server, and for one brand. Presented to the API directly, it is refused.
#What can stop you
| Symptom | Cause | What to do |
|---|---|---|
| The client shows no tool | The server did not start, or the client was not restarted after its configuration was modified | Run npx @sealtrust-io/mcp-server by hand. The startup line must appear. Then restart the client. |
Network error on every tool | The API is not reachable from the machine, or SEALTRUST_API_URL points elsewhere | Check the variable, then the machine's network egress. |
| A call systematically exceeds the timeout | The 15 second timeout is too short for your link | Raise SEALTRUST_TIMEOUT_MS under the env key of your client's configuration, as in point 2, then restart the client. |
found: false on an identifier you know to be right | The form used is not accepted by this tool | Check the form in the identifier table. A certificate number only goes through on verify_product and get_certificate. |
| The tools contradict each other on an item withdrawn from the market | Each tool handles end of life in its own way | verify_product returns status: "unknown". get_passport_proof and get_certificate return found: false. get_passport returns the passport, together with a lifecycle block indicating that the item is no longer current. |
| The passport comes back without an IPFS link | The public access level does not carry it | Use get_passport_proof, which returns the link to the immutable copy when it is published. |
| A 429 error | A call limit has been reached | Space out the calls. The counter restarts after 60 seconds. On the hosted address, the limit can be shared with other users: run the npm package on your machine. |
| The hosted address answers 403 | The request carries an Origin header from a site that is neither Claude nor ChatGPT | Call from an MCP client or from your server, without an Origin header. |
| The "Connect an AI assistant" page says the request has expired | More than 10 minutes went by since the click in Claude, or the request was already answered | Start again from Claude. |
| No brand is offered | Your account administers no brand | Ask an administrator of the brand to give it to you. |
| The page refuses a SealTrust team account | That account sees every brand: it cannot be handed to an assistant | Sign in with an account of the brand. |
| The preparation tools do not appear | "Prepare drafts" was not ticked | End the connection in the console, then connect the connector again in Claude with that permission ticked. |
| Claude asks to sign in again | The connection ended: 90 days went by, it was ended in the console, or the rights on the brand were lost | Sign in again, or ask an administrator of the brand. |
Was this page helpful?
Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.