The Home for Magento 2 Excellence

Quality-tested Magento 2 modules. Explore. Evaluate. Elevate. #magento2

1090 Modules
628 Ready
462 Need Help
🏆 Leaderboard
Actively Maintained v1.0.1

MSR Agentic UCP

mahesh-rajawat/module-agentic-ucp

Adds Universal Commerce Protocol (UCP) support to Magento 2, letting AI agents discover, authenticate (DID + JWT), and transact under policy control. Provides an agent capability manifest at /.well-known/ucp.json, an auth endpoint, policy middleware with rate/order limits and human-confirmation, an admin agent registry, and an audit log.

4
Downloads
Below average
0
GitHub Stars
2mo ago
Last Release
0
Open Issues
Build Passing
Ready to install

Build Tests

Composer Install
DI Compile
Templates

Code Quality

CS Coding Standard
29 warnings
L1 PHPStan

Tested on Magento 2.4.9

Recent Test History

Each release is tested against the latest Magento version at that time.

v1.0.1 on Magento 2.4.9
Jun 7, 2026
v1.0.0 on Magento 2.4.9
Jun 1, 2026

Share This Module's Status

MSR Agentic UCP Magento compatibility status badge

README

Loaded from GitHub

MSR_AgenticUcp — UCP Agentic Commerce Base Module

Adds Universal Commerce Protocol (UCP) support to Magento 2, enabling AI agents to discover, authenticate, and transact on your storefront in a structured, policy-controlled way.

This is the base module. It handles identity, authentication, policy enforcement, and admin configuration. The companion module MSR_AgenticUcpCheckout provides the catalog, cart, checkout, and order REST endpoints.


What this module provides

Feature Where
Agent capability manifest GET /.well-known/ucp.json
Agent authentication (DID + JWT) POST /rest/V1/ucp/auth
Policy middleware (all /V1/ucp/* routes) Plugin/Webapi/AgentPolicyGuard.php
Capability profiles (what agents can do) etc/ucp.xml
Admin configuration UI Stores → Configuration → MSR → Agentic UCP
Extensible capability registry Model/Config/Source/Capabilities.php
Audit trail ucp_audit_log database table

Architecture overview

Admin panel (Stores → Config → MSR → Agentic UCP)
│
├── Agent registry — WHO the agents are
│     name, DID, trust level, profile, active, per-agent overrides
│     stored in: core_config_data (database)
│     no file editing ever needed
│
├── Default policies — global limits
│     rate limit, max order value, human confirmation, TTL
│     stored in: core_config_data (database)
│
└── ucp.xml — capability profiles only
      what each profile CAN do
      stored in: module files (version controlled)
      changed only when: a new feature module is installed

Design principles

Single source of truth — agent identity and policies live in the database (admin panel). Capability profiles live in code (ucp.xml). Never both.

Open/Closed — child modules add capabilities by injecting into Capabilities source model via di.xml. Base module files are never modified.

No hardcoded agents — ucp.xml contains only profile-* entries. Real agents (DIDs) are registered in the admin panel at runtime.


Requirements

Requirement Version
Magento 2.4.4+
PHP 8.1 or 8.2
OpenSSL PHP extension enabled
Redis (recommended) 6.0+ for rate limiting

Installation

Step 1 — Copy the module

unzip MSR_AgenticUcp.zip -d /var/www/html/app/code/

Step 2 — Enable and compile

cd /var/www/html
php bin/magento module:enable MSR_AgenticUcp
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:flush

Step 3 — Add token secret to env.php

php -r "echo bin2hex(random_bytes(32)) . PHP_EOL;"

Open app/etc/env.php and add:

'ucp' => [
    'token_secret' => 'paste-generated-secret-here',
],

Step 4 — Register your first agent in admin

Go to Stores → Configuration → MSR → Agentic UCP → Agent registry.

Click Add agent and fill in:

Field Example value Notes
Agent name My Shopping Agent Human label
DID did:web:yourdomain.com From the agent owner
Trust level Trusted
Capability profile Shopping agent From dropdown
Active Yes
Max order value 500 Blank = use default
Rate limit/min 30 Blank = use default
Allowed payments checkmo Blank = all methods

Step 5 — Verify

curl -sk https://yourstore.com/.well-known/ucp.json | python3 -m json.tool

DID — what to put in the admin config

Situation DID value
You host the agent did:web:yourdomain.com
Agent on a subdomain did:web:agent.yourdomain.com
Agent at a path did:web:yourdomain.com:agents:shopper
Local dev / Warden did:web:default.freshm2.test:agents:test
No server available did:key:z6Mk... (generate below)
Third-party provider Whatever DID they give you

Generate a did:key instantly (no server needed):

npm install -g @digitalbazaar/did-key-cli
npx did-key generate --type Ed25519

Host a did:web on your domain — create and serve at https://yourdomain.com/.well-known/did.json:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:yourdomain.com",
  "verificationMethod": [{
    "id": "did:web:yourdomain.com#key-1",
    "type": "JsonWebKey2020",
    "controller": "did:web:yourdomain.com",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
  }],
  "authentication": ["did:web:yourdomain.com#key-1"],
  "assertionMethod": ["did:web:yourdomain.com#key-1"]
}

Capability profiles

Profiles are defined in etc/ucp.xml. They are templates — real agents are assigned to a profile in the admin panel.

Built-in profiles

Profile ID What it allows
profile-readonly Browse, search, check inventory, track orders
profile-shopping Everything in readonly + manage cart, place orders
profile-full-access Everything including customer data and payment initiation

Built-in capability codes

Code Label Risk
catalog.browse Browse catalog Low
catalog.search Search catalog Low
inventory.query Check inventory Low
cart.manage Manage cart Medium
order.track Track orders Medium
customer.read Read customer data Medium
order.place Place orders High
payment.initiate Initiate payments High
negotiation.price Negotiate pricing High

High-risk capabilities always require human confirmation regardless of the default policy setting.

Capability code format: namespace.action — lowercase, dot-separated. The XSD validates this pattern. Any code matching the pattern is valid — no central registry needed.


Policy middleware

Every /V1/ucp/* request (except /V1/ucp/auth) passes through five checks:

Check Failure
Valid Bearer token 401
Capability granted for this route 403
Rate limit not exceeded 429
Order value within limit (order routes only) 422
Human confirmation present (mutating requests) 400

Admin panel sections

Agent registry

Dynamic grid — one row per AI agent. Profile dropdown is sourced from profile-* entries in ucp.xml across all installed modules. Adding a new module with a new profile automatically adds it to this dropdown.

Capability profiles reference

Read-only table showing what each profile means in plain English. Store owner sees "Browse catalog — View product listings", not catalog.browse. Grouped by risk level.

Default policies

Global defaults that apply to all agents unless overridden per-agent: human confirmation, rate limit, max order value, audit log, token TTL.

Security

Allowed DID methods, DID resolution timeout, and token secret status indicator (shows configured/not configured without exposing the value).

Recent audit log

Inline view of the last 20 agent requests showing agent, path, capability (human label), outcome (colour-coded), and timestamp.


Decision ownership

What Owned by Changed via
Capability profiles Code ucp.xml + deploy
New capability codes Code di.xml injection + deploy
Agent identity (name, DID, trust level) Database Admin panel
Which agents are active Database Admin panel
Per-agent permissions Database Admin panel
Global default policies Database Admin panel
Token secret Server env.php

Nothing about who the agents are or what their limits are should ever require a code deployment.


Extending from another module

Add a new agent at runtime

Admin panel → Agent registry → Add agent. No code, no deployment.

Add a new capability profile

Drop a ucp.xml with a profile-* entry. Appears in admin dropdown after cache:flush. No base module changes.

<!-- YourVendor/YourModule/etc/ucp.xml -->
<config ...>
    <agent id="profile-b2b">
        <capabilities>
            <capability name="catalog.browse"     enabled="true"/>
            <capability name="quote.request"      enabled="true"/>
            <capability name="contract.negotiate" enabled="true"/>
        </capabilities>
    </agent>
</config>

Add new capability codes

Inject into Capabilities source model via di.xml. No base module files touched. New capabilities appear in the admin reference table and are available in profile definitions.

<!-- YourVendor/YourModule/etc/di.xml -->
<type name="MSR\AgenticUcp\Model\Config\Source\Capabilities">
    <arguments>
        <argument name="additionalCapabilities" xsi:type="array">
            <item name="quote_request" xsi:type="array">
                <item name="value"   xsi:type="string">quote.request</item>
                <item name="label"   xsi:type="string">Request a quote</item>
                <item name="comment" xsi:type="string">Agent can request B2B price quotes</item>
                <item name="risk"    xsi:type="string">medium</item>
                <item name="module"  xsi:type="string">YourVendor_YourModule</item>
            </item>
        </argument>
    </arguments>
</type>

When does a child module need ucp.xml?

New REST endpoints only       → NO  (no ucp.xml needed)
New capability codes          → YES (new profile-* entry + di.xml injection)
Only permissions/policies     → NO  (use admin panel)
Only identity/DID changes     → NO  (use admin panel)

Add a custom policy check

<type name="MSR\AgenticUcp\Plugin\Webapi\AgentPolicyGuard">
    <plugin name="my_check" type="YourVendor\YourModule\Plugin\MyPlugin" sortOrder="20"/>
</type>

Hook into auth events

<event name="ucp_agent_authenticated">
    <observer name="my_hook" instance="YourVendor\YourModule\Observer\OnAuth"/>
</event>

Companion module

MSR_AgenticUcpCheckout provides catalog, cart, checkout, and order endpoints. It does not need its own ucp.xml — it only adds REST routes for capabilities already defined in base module profiles.

unzip MSR_AgenticUcpCheckout.zip -d /var/www/html/app/code/
php bin/magento module:enable MSR_AgenticUcpCheckout
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:flush

Local dev setup (Warden)

Apply dev mode patches

Manually patch Model/Did/Resolver.php to bypass HTTP DID resolution and return a local key (see UCP_Testing_Guide.md for full instructions).


Troubleshooting

Error Cause Fix
404 on /.well-known/ucp.json routes.xml has dot in frontName, or Router not registered Check frontName="ucpwellknown" and etc/frontend/di.xml sortOrder=22
"Agent not registered" DID mismatch between admin config and request Check admin panel DID matches POST body exactly
"Could not resolve DID document" Resolver patch not applied (dev) or DID document unreachable (prod) Apply dev patch or verify https://yourdomain.com/.well-known/did.json
"JWT issuer mismatch" JWT iss claim doesn't match the did field Decode JWT with cut -d'.' -f2 | base64 -d and check iss
"UCP token signature invalid" Token secret mismatch Check ucp/token_secret in env.php matches test script
404 instead of 401 on policy test Checkout module not installed Install MSR_AgenticUcpCheckout
"More than one node" XML merge error Repeating elements missing merge key Check $_idAttributes in UcpReader.php covers all list elements
New capability not in admin dropdown di.xml injection not compiled Run setup:di:compile && cache:flush
Rate limit not triggering Redis not configured as cache backend Check env.php cache section uses Redis

This content is fetched directly from the module's GitHub repository. We are not the authors of this content and take no responsibility for its accuracy, completeness, or any consequences arising from its use.