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

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:

Terminal
claude mcp add --transport http sealtrust https://mcp.sealtrust.io/mcp

The 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.

Terminal
npx @sealtrust-io/mcp-server

The 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.

JSON
{
  "mcpServers": {
    "sealtrust": {
      "command": "npx",
      "args": ["-y", "@sealtrust-io/mcp-server"]
    }
  }
}

On the command line with Claude Code, the same declaration is written as follows.

Terminal
claude mcp add sealtrust -- npx -y @sealtrust-io/mcp-server

Restart 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.

VariableDefault valueEffect
SEALTRUST_API_URLhttps://api.sealtrust.ioThe address of the API being queried. Trailing slashes are stripped.
SEALTRUST_TIMEOUT_MS15000The 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_URLthe value of SEALTRUST_API_URLThe 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.

JSON
{
  "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.

FormWhat it looks likeWhere you find it
Serial number12 characters, digits and uppercase letters, for example EXEMP1E00000This 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 charactersReturned 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 identifierA string of digitsThe identifier of the on-chain token, returned under the name token_id.
Certificate numberStarts 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.

ParameterTypeRequiredDescription
identifierstringyesSerial number, identifier hash, token identifier or certificate number.

The response carries a status field that takes five values.

ValueWhat it means
registeredThe 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.
revokedThe certificate has been revoked. The product is to be treated as suspect.
expiredThe certificate has passed its end date.
found_no_certificateThe product exists in the registry and no active certificate is attached to it.
unknownNo 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.

ParameterTypeRequiredDescription
identifierstringyesSerial number, identifier hash or token identifier. A certificate number is not accepted here.
formatstringnojson 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.

ParameterTypeRequiredDescription
identifierstringnoThe item you want the proof for.
gtinstringnoThe 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.

ParameterTypeRequiredDescription
identifierstringyesSerial 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.

ParameterTypeRequiredDescription
identifierstringyesSerial 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.

ParameterTypeRequiredDescription
gtinstringyesThe article code of the model.
serialstringnoThe 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.

ParameterTypeRequiredDescription
identifierstringone of the twoSerial number, identifier hash or token identifier, for the passport of an item.
gtinstringone of the twoThe GTIN of a model, for the passport of that model.
lotstringnoWith 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.

SituationWhat the server returnsWhat to conclude from it
Product, passport or credential untraceableA normal result carrying found: false and the API message, or status: "unknown" for verify_productThe question got an answer. Nothing broke.
API error response other than a 404A 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 refusedA tool error starting with Network errorNo 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.

LimitValueWhat is counted
Per IP address300 requests per minuteEvery request, tools or not. Beyond it, the answer is 429 before the server is reached.
Per client120 tool calls per minuteTool calls only. Listing the tools does not count.
For all users together480 reads per minute on each public read family, 48 on the GS1 resolutionThe 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.

ToolPath calledLimit
verify_productresolution, then certificate600 per minute on each of the two
get_passport, get_passport_proof, verify_credentialpassport600 per minute
get_certificatecertificate600 per minute
get_product_historytimeline600 per minute
resolve_gs1GS1 resolution, then passport60 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 canTools
Read models, batches and passportslist_product_models, get_product_model, list_batches, get_batch, list_passports, get_passport_draft
Read passport templateslist_dpp_templates, get_dpp_template
Say what is missing and what each audience will seeget_readiness, preview_passport
Create and complete models and batchescreate_product_model, update_product_model, create_batch
Open and complete a passport draft, for a model or a batchcreate_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.

  1. In Claude, open Settings, then Connectors, then "Add custom connector". Give it a name, for example SealTrust admin, and the address https://mcp.sealtrust.io/admin/mcp.
  2. Click "Connect". Claude opens the SealTrust console. Sign in with your account, two-factor authentication included if it is on.
  3. 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.
  4. 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.
PointRule
BrandOne only, chosen when you allow. No tool takes a brand as an argument.
Token lifetime30 minutes. Claude renews it on its own, without asking you again.
Connection lifetime90 days at most. Then Claude asks you to sign in again.
SealTrust team accountRefused: sign in with an account of the brand.
PlanThe brand's plan must include the partner API, as for a key.
Limits60 tool calls a minute per connection, 30 API calls a minute per connection.
Number of connections10 at most per person, 25 at most per brand. Beyond, the console asks you to end a connection first.
PasswordChanging 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.

Terminal
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.

VariableRequiredEffect
SEALTRUST_ADMIN_API_KEYyesThe brand's API key.
SEALTRUST_BRAND_CODEnoThe code of the expected brand. If the key belongs to another brand, the server refuses to work.
SEALTRUST_MAX_CALLS_PER_MINUTEnoAPI calls per minute, 30 by default, 120 at most. Beyond it, the tool answers a clear error instead of insisting.
SEALTRUST_API_URLnoThe 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.

JSON
{
  "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.

Terminal
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

  1. Ask the assistant to start from a template: list_dpp_templates, then create_passport_draft with template.
  2. 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.
  3. It reads get_readiness to tell you what is missing, then preview_passport to show you what each audience will see.
  4. 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

SymptomCauseWhat to do
The client shows no toolThe server did not start, or the client was not restarted after its configuration was modifiedRun npx @sealtrust-io/mcp-server by hand. The startup line must appear. Then restart the client.
Network error on every toolThe API is not reachable from the machine, or SEALTRUST_API_URL points elsewhereCheck the variable, then the machine's network egress.
A call systematically exceeds the timeoutThe 15 second timeout is too short for your linkRaise 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 rightThe form used is not accepted by this toolCheck 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 marketEach tool handles end of life in its own wayverify_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 linkThe public access level does not carry itUse get_passport_proof, which returns the link to the immutable copy when it is published.
A 429 errorA call limit has been reachedSpace 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 403The request carries an Origin header from a site that is neither Claude nor ChatGPTCall from an MCP client or from your server, without an Origin header.
The "Connect an AI assistant" page says the request has expiredMore than 10 minutes went by since the click in Claude, or the request was already answeredStart again from Claude.
No brand is offeredYour account administers no brandAsk an administrator of the brand to give it to you.
The page refuses a SealTrust team accountThat account sees every brand: it cannot be handed to an assistantSign in with an account of the brand.
The preparation tools do not appear"Prepare drafts" was not tickedEnd the connection in the console, then connect the connector again in Claude with that permission ticked.
Claude asks to sign in againThe connection ended: 90 days went by, it was ended in the console, or the rights on the brand were lostSign in again, or ask an administrator of the brand.

Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.

Suggest a correctionReport a problem