Platform-Agent Bridge (mcp.astrasync.ai)
One MCP endpoint that lets every platform agent transact with every AstraSync-registered merchant.
One MCP endpoint that lets every platform agent (Claude, ChatGPT, Gemini, Cursor) transact with every AstraSync-registered merchant. The bridge handles protocol normalisation (ACP / AP2 / UCP / x402), forwards the inbound agent's AstraSync identity to the merchant's policy engine, and surfaces structured denials when PDLSS boundaries don't allow a request.
Bridge is transport, merchant is policy. The bridge does not enforce its own trust floor on transactional tools. Every call triggers verify-access against the merchant's endpoint with the inbound agent's credentials forwarded — the merchant decides what to accept. Agents the merchant would happily transact with directly are never blocked at the bridge layer.
No direct merchant HTTP checkout, no CSRF handshake. The bridge is a discovery +
identity-handshake layer: start_checkout and confirm_purchase call AstraSync's own
verify-access and mint a scoped session — they do not POST to your merchant checkout
endpoint. So merchants do not need to expose a CSRF token to the bridge or special-case CSRF
for bridge-mediated flows; CSRF protection on your own checkout routes is unaffected. (Direct
merchant checkout forwarding is a separate, not-yet-shipped capability — when it lands, any CSRF
handshake will be handled by the bridge, never by the agent.)
Tool surface
Nine tools on one MCP server: identity registration (register_agent, request_registration,
poll_registration), doc search (search_docs), verify-access (verify_agent), and commerce
(list_merchants, discover_catalog, start_checkout, confirm_purchase). The four commerce
tools are documented below; identity + verify tools follow standard MCP conventions — see
/docs/agent-access for those.
register_agent
Thin wrapper over the verification-gateway SDK's AstraSync.register(). Pass any of the SDK's
auth modes — { apiKey } (owner step-up email), { email, password } (synchronous active),
{ apiKey, privateKey } (synchronous signed) — plus the standard RegisterOptions (name, pdlss,
model, framework, protocols). Returns SDK's RegisterResult verbatim:
{ status: "active", agent } or { status: "pending_approval", requestId, pollUrl }.
No-creds calls return a structured guidance envelope (registrationUrl, steps[]) mirroring the
same shape the SDK's verify path emits for unauthenticated callers.
poll_registration
Thin wrapper over AstraSync.pollRegistration(requestId). Returns
{ state: "pending" | "approved" | "denied" | "expired", astraId?, agent?, reason? }. Use the
requestId returned by register_agent. The skill defines two polling patterns: conversational
agents poll once on user-confirmation; autonomous agents poll every 5–10s with a 5-minute
timeout.
list_merchants
Discovery surface. Returns AstraSync-registered merchants that opted into platform-agent discoverability. No authentication required.
{
"merchants": [
{
"astraeId": "ASTRAE-shop42",
"name": "ExampleShop",
"surface": "website",
"jurisdictions": ["AU", "NZ"],
"supportedProtocols": ["acp", "ap2"],
"skillUrl": "https://shop.example/mcp/skill.md",
"catalogUrl": "https://shop.example/api/catalog"
}
]
}Finding the merchant's MCP endpoint: the response does not surface mcpUrl as a first-class
field today. Agents needing to reach the merchant's MCP server should fetch the skillUrl above
and read the endpoints.mcp field from the returned skill document. A first-class mcpUrl on
the merchant entry is on the roadmap; in the interim, fetch-the-skill is the supported path.
discover_catalog
Fetches the merchant's registered catalogUrl (not /.well-known/*, which gateways skip-path
and always return the public view). Forwards inbound _meta.astrasync credentials so tiered
catalogs serve the correct tier. Anonymous responses are cached; verified callers always bypass
cache.
Canonical catalog shape:
{
"merchantAstraeId": "ASTRAE-shop42",
"name": "ExampleShop",
"supportedProtocols": ["acp", "ap2"],
"skus": [
{
"id": "sku-001",
"title": "Widget",
"description": "Best-in-class widget",
"price": { "amount": "25.00", "currency": "USD" },
"availability": "in_stock",
"protocol": "acp",
"raw": { /* merchant's native shape, untouched */ }
}
],
"fetchedAt": "2026-05-15T10:00:00.000Z",
"cached": false,
"tier": "verified"
}The raw field on each SKU is the merchant's native protocol shape, preserved verbatim. Drop
down to it when the canonical fields elide something protocol-specific.
start_checkout
Initiates a checkout against a merchant. Calls verify-access with
purpose: "shopping.purchase" against the merchant's endpoint. Returns a sessionId + intent
mandate on grant; a structured denial otherwise.
{
"success": true,
"sessionId": "cks_…",
"merchantAstraeId": "ASTRAE-shop42",
"intentMandate": {
"agentId": "ASTRA-XYZ…",
"merchant": "ASTRAE-shop42",
"items": [{ "sku": "sku-001", "quantity": 2 }],
"totalValue": 50,
"currency": "USD",
"issuedAt": "...",
"expiresAt": "..."
},
"requiredScopes": ["shopping.purchase"],
"tokenLifetime": 1800000,
"accessLevel": "standard"
}confirm_purchase
Completes a session. Re-validates trust + scope against the merchant via verify-access with
purpose: "shopping.purchase" (same canonical purpose token as start_checkout —
checkout-create and checkout-confirm are two phases of one shopping intent), plus the
commerce-pipeline's payment-mandate checks server-side.
{
"success": true,
"verificationResult": {
"identityVerified": true,
"policyAllowed": true,
"accessLevel": "standard",
"recommendation": "grant",
"correlationId": "cor_…"
},
"txHash": "astrasync-placeholder:cor_…",
"txHashKind": "astrasync-correlation-placeholder",
"receiptUrl": "https://astrasync.ai/receipts/cor_…",
"merchantAstraeId": "ASTRAE-shop42",
"items": ["..."],
"totalValue": 50,
"currency": "USD"
}txHash is a placeholder until v2. The txHashKind: "astrasync-correlation-placeholder"
discriminator tells you not to verify it on a public blockchain. Use receiptUrl for
confirmation today. Blockchain commit lands in a separate v2 PR.
Purpose tokens the bridge emits
When the bridge calls verify-access on your behalf (Path B), it passes a canonical PDLSS
purpose token. The vocabulary stays disjoint from transport tokens (no mcp_invoke) and reuses
the existing PDLSS shopping / identity / discovery namespaces — so your endpoint's PDLSS scope
allowlist doesn't have to grow a new sub-namespace just to support bridge traffic.
When declaring an agent's allowedActions or scope.resources, MCP traffic uses
<method>:<toolName> action encoding and mcp:tool/<name> resource encoding — see
Declaring allowedActions and scope.resources for MCP traffic
on the agent-access docs for the worked example.
| Bridge tool | Purpose | Action | When fired |
|---|---|---|---|
discover_catalog | shopping | shopping.search | Catalog browse, merchant filtering, SKU search. |
start_checkout | shopping | shopping.purchase | Cart → checkout transition (intent mandate issued). |
confirm_purchase | shopping | shopping.purchase | Final purchase confirmation (same purpose — checkout-create and checkout-confirm are two phases of one shopping intent). |
verify_agent | identity | caller-supplied | Verify-access check (allowed/denied + trust score). Pass an optional purpose (bare category; defaults to identity) and a required dotted-verb action. |
list_merchants | discovery | discovery.read | Bridge-discoverable merchant listing. |
search_docs | discovery | discovery.read | Docs / FAQ search. |
Path B merchants: route allowedPurposes take the bare category nouns; agents enumerate the
dotted actions in their allowedActions. If an agent declares shopping.purchase but not
shopping.search, it gets a successful start_checkout but a denied discover_catalog —
declare the granularity that fits.
| Purpose category (bare noun) | Actions (dotted verbs) | Covers |
|---|---|---|
| shopping | shopping.search, shopping.purchase | Catalog browse/search; checkout create + confirm (one purchase intent) |
| identity | identity.verify, identity.lookup | Trust/score verification; identity resolution |
| discovery | discovery.read | Merchant listing, docs search |
| data | data.read, data.write, data.delete | Generic API access — the fallback pair for unmapped routes (data.execute is reserved) |
| custom (e.g. trading, accounting) | trading.execute, accounting.read, … | Any bare noun + dotted verbs under it — first-class, not second-class |
allowedActionsis required (min 1) — the evaluator is fail-closed on actions.categoriesis derived from the dotted-action prefixes; supply extras only to widen.- MCP tool names (
list_products) are valid enumerated actions; they derive no category, so add an explicit one if all your actions are dotless. - Transport verbs (GET/POST) never travel as actions — HTTP senders map them through the pinned table (GET → data.read, POST/PUT/PATCH → data.write, DELETE → data.delete).
- Retired gen-1 tokens (
read_data,write_data,execute_action) are rejected at registration — use thedatacategory.
Structured denial shape
When start_checkout or confirm_purchase denies a request, the response uses the same envelope
as the platform's verify-access route (so a single parser handles bridge + direct verify-access
responses interchangeably).
{
"success": true,
"access": {
"allowed": false,
"reason": "Caller did not present an AstraSync agent identity",
"failures": [
{
"code": "agent_missing",
"message": "No _meta.astrasync.agentId provided.",
"dimension": "agent.missing"
}
],
"requiresStepUp": false,
"requiresApproval": false
},
"recommendation": "deny",
"recommendationReasons": ["..."],
"correlationId": "cor_..."
}The failures[].dimension field is the literal string to switch on for error handlers.
Vocabulary below.
Deny propagation today: when a Path B merchant's PDLSS denies a bridge request, the bridge
propagates the merchant's deny verbatim as a JSON-RPC error. There is no anonymous step-down
behaviour today — agents whose PDLSS scope conflicts with merchant policy see the merchant's
deny shape directly. Anonymous step-down (bridge re-fetching the restricted-tier catalog and
returning it with a tier: "stepped_down" indicator) is on the roadmap as a later-round bridge
enhancement.
failures[].dimension vocabulary
| dimension | Example reason |
|---|---|
agent.missing | No _meta.astrasync provided (transactional tools only) |
agent.lookup | agentId provided but not registered with AstraSync |
agent.status | Agent deactivated or revoked |
pdlss.purpose | Merchant policy doesn't allow commerce.checkout.create for this agent |
pdlss.limits | Cart total exceeds the agent's autonomous threshold |
pdlss.scope | Merchant URL outside the agent's allowed scope list |
counterparty.allowlist | Merchant requires allowlist + caller not on it |
counterparty.trust | Caller's trust score below merchant's floor |
attestation.type | Payment-mandate type not accepted by merchant |
endpoint.deactivated | Merchant endpoint deactivated |
upstream.validation_failed | Platform reached but rejected the request as invalid — fix the input, then retry |
upstream.auth_failed | Platform rejected the bridge credentials (authentication) |
upstream.access_denied | Platform reached but denied access for this call (authorization) |
upstream.unexpected_status | Platform returned an unexpected 4xx — inspect the body before retrying |
system.platform_unreachable | MCP bridge couldn't reach the AstraSync platform (5xx/network/DNS/timeout — retry, and check ASTRASYNC_API_URL uses the canonical apex form https://astrasync.ai/api) |
Discovery + skill
- Discovery doc:
https://mcp.astrasync.ai/.well-known/mcp.json - Anthropic Skill:
https://mcp.astrasync.ai/skill.md
The skill markdown covers two tracks: tool-capable agents (the default modern chat surface) call
register_agent on the MCP server directly, with conversational or autonomous polling patterns;
tool-less chat agents are advised to switch to a client with tool access. All 10 tools — identity
registration, agent lookup, doc search, verify-access, and commerce — live on the single /mcp
surface.
Opt your endpoint into the bridge. In your AstraSync dashboard under
Endpoints → [your endpoint] → Platform-Agent Bridge, set Discoverability: Discoverable
and register a Catalog URL (gateway-evaluated path for tiered content; not
/.well-known/*). Optionally add a Skill URL pointing at your own merchant-specific MCP
server or Anthropic Skill.

