XGR MCP Gateway — Setup & Configuration
Document ID: XGR-MCP-SETUP
Last updated: 2026-08-15
Audience: Operators self-hosting the gateway
Implementation status: Live
Source of truth: xgr-network/xgr-mcp
Self-hosting only
Most users should connect directly to the hosted mainnet or testnet MCP endpoint. This page is for operators running their own gateway instance.
Hosted endpoints
Mainnet
https://mcp.xgr.network/mcp
Testnet
https://mcp.testnet.xgr.network/mcp
Testnet Faucet
https://faucet.xgr.network
Prerequisites
A complete self-hosted deployment requires:
- Node.js with ESM support,
- npm,
- an XGRChain JSON-RPC endpoint,
- an XGR Explorer API,
- read-only access to the Explorer PostgreSQL database for DB-backed analytics,
- persistent storage for operation handoffs,
- access to
xgr-network/XGRduring documentation synchronization, - correctly configured xDaLa Workbench URLs.
The current public implementation additionally exposes Explorer-backed:
- native-XGR relation graphs,
- graph-edge transaction lookup,
- transaction relation tracing,
- native-XGR value-flow analysis,
- XDaLa Session Start payload history.
The connected Explorer installation must therefore support the corresponding API and indexed database structures.
When purchase tools are enabled, the deployment additionally requires:
- access to the XGR purchase API,
- HTTPS connectivity outside localhost,
- a mainnet-only purchase configuration,
- an autonomous EUR policy no greater than
249.99.
When starter gas is enabled, the deployment additionally requires:
- a dedicated low-balance XGR service wallet,
- a service-only private key supplied through the process environment,
- a persistent writable SQLite path,
- matching Node.js ABI versions during installation and runtime,
- correct reverse-proxy topology for client-IP enforcement,
- explicit hourly, daily, address and balance policies.
Never reuse the starter-gas key from:
- a treasury wallet,
- a validator,
- an exchange wallet,
- a user wallet,
- a deployment wallet,
- an operational hot wallet with significant funds.
Install
git clone https://github.com/xgr-network/xgr-mcp.git
cd xgr-mcp
npm install
cp .env.example .env
npm run typecheck
npm test
npm run build
A production deployment should normally use:
npm ci
when a committed lock file is available.
Build-time documentation synchronization
The build command synchronizes canonical documentation from:
xgr-network/XGR
The generated local XGR/ directory is build output and must not be maintained independently.
When anonymous GitHub access is unavailable, set either:
GITHUB_TOKEN=github_pat_...
or:
GH_TOKEN=github_pat_...
The minimum fine-grained repository permission is:
Contents: Read-only
Typical GitHub failures:
| Status | Meaning |
|---|---|
401 |
Token invalid, expired or revoked |
403 |
Token recognized but unauthorized |
404 |
Repository or requested content unavailable |
The process environment takes precedence over .env.
Run modes
Local stdio
Development:
npm run dev
Production:
npm start
HTTP
Development:
npm run dev:http
Production:
npm run start:http
The HTTP server exposes:
POST /mcp
GET /health
GET /mcp and DELETE /mcp are not supported.
Raw HTTP and SSE framing
MCP HTTP responses may use Server-Sent Events framing.
Example tool listing:
curl -sS -X POST "http://127.0.0.1:3100/mcp" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}' \
| sed -n 's/^data:[[:space:]]*//p' \
| jq
Normal MCP clients handle framing automatically.
Core configuration
| Variable | Purpose | Mainnet example |
|---|---|---|
XGR_RPC_URL |
Connected XGRChain RPC | https://rpc.xgr.network |
XGR_EXPLORER_API_URL |
Explorer API base | https://explorer.xgr.network/api |
MCP_SERVER_NAME |
MCP server name | xgr-mcp-gateway-mainnet |
MCP_READONLY |
Normal user-operation mode | true |
MCP_HTTP_HOST |
HTTP bind address | 127.0.0.1 |
MCP_HTTP_PORT |
HTTP bind port | 3100 |
Optional state-changing feature registration is controlled independently through:
XGR_PURCHASE_*
XGR_STARTER_GAS_*
MCP_READONLY=true describes ordinary user operations.
It does not automatically enable or disable purchase or starter-gas functionality.
Read-only relation-graph, value-flow and payload-history tools do not require a separate feature gate in the current implementation.
Explorer API requirements
The configured:
XGR_EXPLORER_API_URL
is used for Explorer-backed transaction, session and graph evidence.
The current relation and value-flow implementation requires Explorer routes equivalent to:
/v2/addresses/:address/graph
/v2/addresses/:address/graph/neighbors
/v2/graph/edge-transactions
/v2/value-flow/transactions/:txHash
With:
XGR_EXPLORER_API_URL=https://explorer.xgr.network/api
the gateway therefore calls endpoints below:
https://explorer.xgr.network/api/v2/...
Operators must ensure the connected Explorer version supports these routes.
The affected MCP tools are:
get_address_relation_graph
expand_address_relation_graph
trace_xgr_transaction
trace_xgr_value_flow
get_relation_edge_transactions
These tools are read-only.
No private key is required.
Explorer database configuration
Use a dedicated read-only database role.
| Variable | Purpose | Example |
|---|---|---|
PGRO_HOST |
Database host | 127.0.0.1 |
PGRO_PORT |
Database port | 5432 |
PGRO_USER |
Read-only user | xgr_reader |
PGRO_PASSWORD |
Read-only password | secret |
PGRO_DB |
Explorer database | xgrscan |
PGRO_POOL_MAX |
Maximum pool connections | 4 |
PGRO_STATEMENT_TIMEOUT_MS |
Query timeout | 5000 |
The PostgreSQL credentials used by the MCP should not have mutation permissions.
XDaLa start-payload-history requirements
The tool:
get_xdala_start_payload_history
reads indexed XDaLa execution evidence directly through the read-only Explorer database adapter.
The current implementation queries:
tx_receipts
and depends on indexed fields equivalent to:
receipt_from_address
engine_session_id
engine_ostc_id
engine_step_id
engine_orchestration
engine_payload
tx_hash
block_number
updated_at
The database account remains read-only.
The tool performs no database mutation.
For each matching:
owner + sessionId
it selects the first matching entry-step receipt and aggregates scalar payload values in gateway memory.
If the connected Explorer schema does not provide the required indexed fields, this tool cannot return valid history even if it is registered by the MCP server.
Operation storage
| Variable | Purpose | Example |
|---|---|---|
MCP_OPERATION_STORE_DIR |
Root handoff storage directory | /var/lib/xgr-mcp/operations |
MCP_PUBLIC_BASE_URL |
Public gateway base | https://mcp.xgr.network |
MCP_OPERATION_PUBLIC_BASE_URL |
Legacy-compatible alias | https://mcp.xgr.network |
MCP_OPERATION_DEFAULT_TTL_SECONDS |
Default operation TTL | 3600 |
MCP_OPERATION_MAX_TTL_SECONDS |
Maximum operation TTL | 86400 |
MCP_PUBLIC_BASE_URL takes precedence over:
MCP_OPERATION_PUBLIC_BASE_URL
Bundle-deploy handoffs
| Variable | Purpose | Mainnet example |
|---|---|---|
MCP_BUNDLE_DEPLOY_STORE_DIR |
Optional store override | /var/lib/xgr-mcp/operations/bundle-deploy |
MCP_XDALA_BUNDLE_DEPLOY_BASE_URL |
Workbench import base | https://xdala.xgr.network/api/bundle-deploy |
MCP_BUNDLE_DEPLOY_DEFAULT_TTL_SECONDS |
Default TTL | 3600 |
MCP_BUNDLE_DEPLOY_MAX_TTL_SECONDS |
Maximum TTL | 86400 |
If no bundle-deploy storage override is configured, the implementation may derive its storage path from the main operation store.
Session-start handoffs
| Variable | Purpose | Mainnet example |
|---|---|---|
MCP_SESSION_START_STORE_DIR |
Optional store override | /var/lib/xgr-mcp/operations/session-start |
MCP_XDALA_SESSION_START_BASE_URL |
Workbench Session Start base | https://xdala.xgr.network/session-start |
MCP_SESSION_START_DEFAULT_TTL_SECONDS |
Default TTL | 3600 |
MCP_SESSION_START_MAX_TTL_SECONDS |
Maximum TTL | 86400 |
Configure Workbench URLs for the same network as the connected RPC and Explorer.
Mainnet XGR purchase tools
Purchase tools are disabled by default.
Example:
XGR_PURCHASE_TOOLS_ENABLED=true
XGR_PURCHASE_NETWORK=mainnet
XGR_PURCHASE_API_BASE_URL=https://xgr.network
XGR_PURCHASE_MAX_EUR=249.99
Purchase variables
| Variable | Purpose | Required behavior |
|---|---|---|
XGR_PURCHASE_TOOLS_ENABLED |
Feature gate | Must be exactly true. |
XGR_PURCHASE_NETWORK |
Purchase environment | Must be exactly mainnet. |
XGR_PURCHASE_API_BASE_URL |
Purchase API base | HTTPS outside localhost. |
XGR_PURCHASE_MAX_EUR |
Autonomous estimated EUR policy | Positive and no greater than 249.99. |
When enabled, the gateway registers:
get_xgr_purchase_options
quote_xgr_purchase
create_xgr_purchase_order
create_xgr_purchase_order_by_budget
Purchase tools create live backend orders where applicable.
They do not send the stablecoin payment.
Approved order responses return a structured:
payment_instruction
External payment is permitted only when:
payment_approved = true
next_action = external_crypto_payment
A blocked or uncertain order uses:
next_action = do_not_pay
Purchase policy notes
The autonomous MCP purchase policy is limited by:
XGR_PURCHASE_MAX_EUR
The public configuration maximum is:
249.99 EUR
This is an MCP policy limit.
It must not be confused with backend billing-address rules.
The purchase backend may independently require additional billing information at higher order values.
A purchase error after an order POST must not be handled by blindly repeating the order.
Native XGR starter-gas service
Starter gas is disabled by default.
Example:
XGR_STARTER_GAS_ENABLED=true
XGR_STARTER_GAS_NETWORK=mainnet
XGR_STARTER_GAS_CHAIN_ID=1643
XGR_STARTER_GAS_PRIVATE_KEY=0x...
XGR_STARTER_GAS_MAX_RECIPIENT_BALANCE_XGR=0.1
XGR_STARTER_GAS_MAX_HOURLY_GRANTS=20
XGR_STARTER_GAS_MAX_DAILY_GRANTS=100
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_HOUR=5
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_DAY=20
XGR_STARTER_GAS_MAX_ATTEMPTS_PER_ADDRESS=2
XGR_STARTER_GAS_RESERVATION_TIMEOUT_SECONDS=600
XGR_STARTER_GAS_DB_PATH=/var/lib/xgr-mcp/starter-gas-grants-mainnet.sqlite
These values are configuration examples.
Hosted deployments may use different policy values.
Clients must read the active deployment policy through:
get_xgr_starter_gas_options
instead of assuming the .env.example defaults.
Starter-gas variables
| Variable | Purpose |
|---|---|
XGR_STARTER_GAS_ENABLED |
Explicit service gate. Must be true. |
XGR_STARTER_GAS_NETWORK |
mainnet, testnet or devnet. |
XGR_STARTER_GAS_CHAIN_ID |
Expected connected chain ID. |
XGR_STARTER_GAS_PRIVATE_KEY |
Dedicated service-wallet private key. |
XGR_STARTER_GAS_MAX_RECIPIENT_BALANCE_XGR |
Maximum eligible recipient balance. |
XGR_STARTER_GAS_MAX_HOURLY_GRANTS |
Global grant cap over a rolling hour. |
XGR_STARTER_GAS_MAX_DAILY_GRANTS |
Global grant cap for the UTC day. |
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_HOUR |
Per-client-IP request cap over a rolling hour. |
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_DAY |
Per-client-IP request cap for the UTC day. |
XGR_STARTER_GAS_MAX_ATTEMPTS_PER_ADDRESS |
Maximum bounded attempts for an address. |
XGR_STARTER_GAS_RESERVATION_TIMEOUT_SECONDS |
Expiry for stale pre-broadcast reservations. |
XGR_STARTER_GAS_DB_PATH |
Persistent SQLite database path. |
XGR_STARTER_GAS_STORE_PATH |
Legacy JSON import path only. |
Chain defaults
| Network | Default chain ID |
|---|---|
| Mainnet | 1643 |
| Testnet | 1879 |
| Devnet | 1887 |
The connected RPC chain ID is verified before a starter-gas grant is sent.
Registered starter-gas tools
When enabled:
get_xgr_starter_gas_options
request_xgr_starter_gas
Financial behavior
The grant amount is fixed:
1 XGR
It is not configurable by the tool caller.
The request accepts:
address
purpose
purpose is optional descriptive metadata.
The tool never accepts:
privateKey
seed
mnemonic
signature
wallet password
Starter-gas persistent state
The SQLite grant lifecycle uses:
reserved
broadcast
confirmed
failed
The database also stores per-IP request timestamps.
SQLite is configured with:
journal_mode = WAL
busy_timeout = 5000
Reservation and rate-limit operations use transactional locking.
A grant already recorded as broadcast must not simply be sent again.
The service first reconciles its transaction receipt.
Starter-gas storage permissions
The service user requires:
- read and write access to the SQLite file,
- create access in the database parent directory,
- read access to application files,
- access to the configured environment.
Example:
sudo mkdir -p /var/lib/xgr-mcp
sudo chown -R <service-user>:<service-group> /var/lib/xgr-mcp
sudo chmod 750 /var/lib/xgr-mcp
The environment file containing:
XGR_STARTER_GAS_PRIVATE_KEY
must not be readable by unrelated users.
SQLite deployment constraint
Use one active MCP process per starter-gas SQLite database.
Do not mount the same SQLite file concurrently across multiple hosts.
For horizontally scaled gateway deployments, starter-gas accounting requires a shared transactional grant and rate-limit backend instead of independent access to one SQLite file.
Legacy starter-gas JSON migration
XGR_STARTER_GAS_STORE_PATH exists only for legacy migration.
When it points to a legacy JSON file and no SQLite database exists, confirmed legacy records may be imported once into a sibling SQLite database.
Do not reuse a starter-gas database between networks.
In particular, do not reuse a Devnet or Testnet database on Mainnet.
Reverse proxy and client-IP limits
The gateway trusts forwarded IP headers only when the direct socket peer is loopback.
Recommended topology:
Internet
↓
reverse proxy
↓ 127.0.0.1
XGR MCP process
Supported forwarding headers:
X-Forwarded-For
X-Real-IP
The first valid address in:
X-Forwarded-For
is used.
When the direct peer is not loopback, the direct socket address is used and forwarded headers are ignored.
This prevents arbitrary public clients from supplying trusted forwarding headers.
A reverse proxy connected through a Docker bridge or another non-loopback interface will not provide individual forwarded client IPs under the current trust policy.
Only:
request_xgr_starter_gas
consumes starter-gas per-IP quota.
Normal MCP reads are not affected by the starter-gas IP limits.
Starter-gas limit failures are returned as MCP tool errors rather than HTTP 429.
Native dependency and Node.js ABI
The project uses:
better-sqlite3
for starter-gas persistence.
better-sqlite3 is a native Node.js dependency.
It must be installed or rebuilt with the same Node.js ABI used by the runtime service.
An ABI mismatch may produce errors such as:
NODE_MODULE_VERSION mismatch
Clean rebuild:
rm -rf node_modules
npm ci
npm rebuild better-sqlite3
npm run typecheck
npm test
npm run build
Health check
curl -sS http://127.0.0.1:3100/health | jq
A starter-gas-enabled deployment may expose metadata similar to:
{
"ok": true,
"name": "xgr-mcp-gateway-mainnet",
"readOnly": true,
"userOperationsReadOnly": true,
"starterGasEnabled": true,
"serverSigningScope": "dedicated_starter_gas_service_wallet_only",
"userOrThirdPartyPrivateKeysAccepted": false
}
readOnly or userOperationsReadOnly describes normal user-controlled operations.
An explicitly enabled starter-gas service is the narrow service-wallet signing exception.
Verify tool registration
List all registered tools:
curl -sS -X POST http://127.0.0.1:3100/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
--data '{
"jsonrpc":"2.0",
"id":1,
"method":"tools/list",
"params":{}
}' \
| sed -n 's/^data:[[:space:]]*//p' \
| jq -r '.result.tools[]?.name'
Verify graph and value-flow tools
curl -sS -X POST http://127.0.0.1:3100/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
--data '{
"jsonrpc":"2.0",
"id":1,
"method":"tools/list",
"params":{}
}' \
| sed -n 's/^data:[[:space:]]*//p' \
| jq -r '.result.tools[]?.name' \
| grep -E 'relation_graph|trace_xgr|relation_edge'
Expected:
get_address_relation_graph
expand_address_relation_graph
trace_xgr_transaction
trace_xgr_value_flow
get_relation_edge_transactions
Verify payload-history tool
Expected:
get_xdala_start_payload_history
Verify purchase tools
When purchase tooling is enabled:
get_xgr_purchase_options
quote_xgr_purchase
create_xgr_purchase_order
create_xgr_purchase_order_by_budget
Verify starter-gas tools
When starter gas is enabled:
get_xgr_starter_gas_options
request_xgr_starter_gas
Validation before restart
Before deploying a changed MCP version:
npm install
npm run typecheck
npm test
npm run build
For reproducible production installs prefer:
npm ci
npm run typecheck
npm test
npm run build
Do not restart the production service after a failed:
- typecheck,
- test,
- build.
Graph-tool smoke test
Use a known public XGRChain address.
Verify:
get_address_relation_graph
with a small graph first.
Then verify:
expand_address_relation_graph
and:
get_relation_edge_transactions
for a returned edge.
For a known native-XGR transaction, verify:
trace_xgr_transaction
trace_xgr_value_flow
Confirm that:
- the connected Explorer environment is correct,
- graph bounds are respected,
- truncation metadata is preserved,
- relation data is not presented as identity evidence,
- value-flow output is presented as attribution rather than per-coin proof.
XDaLa payload-history smoke test
Use a known deployed XRC-729 workflow with historical sessions.
Call:
get_xdala_start_payload_history
with the correct:
xrc729Address
ostcId
stepId
Confirm:
source = explorer_db
and inspect:
sampledSessions
valuesByField
Verify that:
- historical sessions are returned,
- scalar values are aggregated,
__*internal payload keys are excluded,- the data is treated as historical evidence rather than current schema defaults.
Controlled Mainnet starter-gas test
A Mainnet starter-gas test is a real financial and on-chain operation.
Use:
- one controlled address,
- an address below the configured live balance threshold,
- exactly one grant request,
- a clear test purpose.
First call:
get_xgr_starter_gas_options
and verify the live policy.
Expected successful grant fields include:
network = mainnet
chain_id = 1643
grant_created = true
grant_status = confirmed
amount_xgr = 1
transaction_hash = 0x...
repeat_allowed = false
Do not repeat the request for a confirmed address.
Mainnet example
XGR_RPC_URL=https://rpc.xgr.network
XGR_EXPLORER_API_URL=https://explorer.xgr.network/api
MCP_SERVER_NAME=xgr-mcp-gateway-mainnet
MCP_READONLY=true
MCP_HTTP_HOST=127.0.0.1
MCP_HTTP_PORT=3100
PGRO_HOST=127.0.0.1
PGRO_PORT=5432
PGRO_USER=xgr_reader
PGRO_PASSWORD=
PGRO_DB=xgrscan
PGRO_POOL_MAX=4
PGRO_STATEMENT_TIMEOUT_MS=5000
MCP_OPERATION_STORE_DIR=/var/lib/xgr-mcp/operations
MCP_PUBLIC_BASE_URL=https://mcp.xgr.network
MCP_XDALA_BUNDLE_DEPLOY_BASE_URL=https://xdala.xgr.network/api/bundle-deploy
MCP_XDALA_SESSION_START_BASE_URL=https://xdala.xgr.network/session-start
MCP_PUBLIC_HANDOFF_ALLOWED_ORIGINS=https://xdala.xgr.network
XGR_PURCHASE_TOOLS_ENABLED=true
XGR_PURCHASE_NETWORK=mainnet
XGR_PURCHASE_API_BASE_URL=https://xgr.network
XGR_PURCHASE_MAX_EUR=249.99
XGR_STARTER_GAS_ENABLED=true
XGR_STARTER_GAS_NETWORK=mainnet
XGR_STARTER_GAS_CHAIN_ID=1643
XGR_STARTER_GAS_PRIVATE_KEY=0x...
XGR_STARTER_GAS_MAX_RECIPIENT_BALANCE_XGR=0.1
XGR_STARTER_GAS_MAX_HOURLY_GRANTS=20
XGR_STARTER_GAS_MAX_DAILY_GRANTS=100
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_HOUR=5
XGR_STARTER_GAS_MAX_REQUESTS_PER_IP_DAY=20
XGR_STARTER_GAS_MAX_ATTEMPTS_PER_ADDRESS=2
XGR_STARTER_GAS_RESERVATION_TIMEOUT_SECONDS=600
XGR_STARTER_GAS_DB_PATH=/var/lib/xgr-mcp/starter-gas-grants-mainnet.sqlite
The 0.1 XGR recipient-balance value above is an example configuration matching the repository default.
It is not guaranteed to match the hosted Mainnet policy.
Use:
get_xgr_starter_gas_options
for the active hosted value.
Testnet example
XGR_RPC_URL=https://rpc1.testnet.xgr.network
XGR_EXPLORER_API_URL=https://explorer.testnet.xgr.network/api
MCP_SERVER_NAME=xgr-mcp-gateway-testnet
MCP_READONLY=true
MCP_HTTP_HOST=127.0.0.1
MCP_HTTP_PORT=3100
PGRO_HOST=127.0.0.1
PGRO_PORT=5432
PGRO_USER=xgr_reader
PGRO_PASSWORD=
PGRO_DB=xgrscan
PGRO_POOL_MAX=4
PGRO_STATEMENT_TIMEOUT_MS=5000
MCP_PUBLIC_BASE_URL=https://mcp.testnet.xgr.network
MCP_XDALA_BUNDLE_DEPLOY_BASE_URL=https://xdala.testnet.xgr.network/api/bundle-deploy
MCP_XDALA_SESSION_START_BASE_URL=https://xdala.testnet.xgr.network/session-start
XGR_PURCHASE_TOOLS_ENABLED=false
XGR_STARTER_GAS_ENABLED=false
Public HTTP routes
| Route | Method | Purpose |
|---|---|---|
/health |
GET |
Health, runtime and signing-scope metadata |
/mcp |
POST |
Stateless MCP endpoint |
/operations/:id |
GET |
Generic operation page |
/api/operations/:id |
GET |
Generic operation state |
/api/operations/:id/status |
POST |
Generic operation callback |
/api/bundle-deploy/:handle |
GET |
Fetch bundle-deploy handoff |
/api/bundle-deploy/:handle/status |
POST |
Record deployment status |
/api/bundle-deploy/:handle/result |
POST |
Record terminal deployment result |
/api/session-start/:handle |
GET |
Fetch Session Start handoff |
/api/session-start/:handle/result |
POST |
Record terminal Session Start result |
Purchase and starter-gas functionality does not add separate public HTTP routes.
Relation graph, value-flow and payload-history functionality also does not add separate MCP Gateway routes.
These capabilities are exposed as tools through:
POST /mcp
The graph and value-flow tools internally call the configured Explorer API.
Deployment checklist
Before exposing an MCP instance publicly:
- verify the RPC chain ID,
- verify the Explorer API network,
- verify the Explorer API supports the relation-graph endpoints,
- verify the Explorer API supports native-XGR value-flow analysis,
- confirm Explorer PostgreSQL credentials are read-only,
- confirm the Explorer database exposes the required XDaLa receipt fields,
- set the correct public MCP URL,
- set network-matching Workbench URLs,
- configure allowed Workbench origins,
- verify handoff rate limits,
- verify audit-log permissions,
- verify handoff storage permissions,
- verify TTL values,
- call
get_xgr_network_info, - call
get_chain_status, - test a small address relation graph,
- test one known transaction trace,
- test one known native-XGR value-flow request,
- test one known XDaLa payload-history query,
- create and cancel a test handoff,
- verify no secret appears in public responses.
When purchase tools are enabled:
- confirm
XGR_PURCHASE_NETWORK=mainnet, - confirm
XGR_PURCHASE_MAX_EUR <= 249.99, - call
get_xgr_purchase_options, - inspect the returned payment assets,
- inspect
requires_sender_wallet, - inspect machine-readable agent guidance,
- create only a controlled low-value test order,
- verify an approved order contains an exact
payment_instruction, - verify blocked orders return
do_not_pay, - verify the MCP does not send the stablecoin payment.
When starter gas is enabled:
- confirm the service wallet is dedicated,
- keep the service wallet intentionally low balance,
- confirm the private key belongs only to that service wallet,
- confirm the configured RPC chain ID,
- confirm the SQLite path is persistent,
- confirm the service user can write to the SQLite directory,
- confirm the database is not shared concurrently across hosts,
- confirm the runtime Node.js ABI matches
better-sqlite3, - confirm forwarded IPs are trusted only through loopback,
- call
get_xgr_starter_gas_options, - verify all live caps,
- perform exactly one controlled grant test,
- verify the transaction confirms,
- verify the same address cannot receive another confirmed grant,
- monitor service-wallet balance,
- monitor
failed,broadcastandconfirmedrecords, - monitor hourly and daily usage.