@agentsbloom/sdk 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AgentsBloom
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,254 @@
1
+ <p align="center">
2
+ <a href="https://agentsbloom.com">
3
+ <img src="./assets/logo-mark.svg" alt="AgentsBloom lotus mark" width="96" height="96" />
4
+ </a>
5
+ </p>
6
+
7
+ <h1 align="center">@agentsbloom/sdk</h1>
8
+
9
+ <p align="center">
10
+ <strong>One install makes your Express store agent-ready.</strong><br />
11
+ Expose commerce actions to AI agents through open discovery surfaces and secure agent-commerce protocols.
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://docs.agentsbloom.com">Docs</a> ·
16
+ <a href="https://agentsbloom.com">Marketing</a> ·
17
+ <a href="https://blog.agentsbloom.com">Blog</a> ·
18
+ <a href="https://github.com/AgentsBloom">AgentsBloom on GitHub</a>
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="https://www.npmjs.com/package/@agentsbloom/sdk"><img src="https://img.shields.io/npm/v/@agentsbloom/sdk?logo=npm&logoColor=white&label=npm" alt="npm version" /></a>
23
+ <a href="https://github.com/AgentsBloom/sdk/actions/workflows/ci.yml"><img src="https://github.com/AgentsBloom/sdk/actions/workflows/ci.yml/badge.svg" alt="CI status" /></a>
24
+ <a href="https://github.com/AgentsBloom/sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-7c3aed.svg" alt="MIT license" /></a>
25
+ </p>
26
+
27
+ ## About AgentsBloom
28
+
29
+ [AgentsBloom](https://agentsbloom.com) builds open infrastructure for commerce on the agentic web. We help teams make existing server-side commerce actions understandable and usable by software agents while keeping the store in control of its catalog, authorization, inventory, checkout, and payment logic.
30
+
31
+ This SDK is the open-source Node.js/Express core: a small middleware layer that gives an existing Express store a clear path to agent-ready commerce.
32
+
33
+ ## One install to make an Express store agent-ready
34
+
35
+ ```sh
36
+ npm install @agentsbloom/sdk express
37
+ ```
38
+
39
+ Then add the middleware and describe your store actions:
40
+
41
+ ```js
42
+ import express from "express";
43
+ import { agentsbloom } from "@agentsbloom/sdk";
44
+
45
+ const app = express();
46
+
47
+ app.use(express.json({ limit: "1mb" }));
48
+ app.use(agentsbloom({
49
+ baseUrl: process.env.PUBLIC_STORE_URL,
50
+ actions: {
51
+ search: {
52
+ method: "POST",
53
+ description: "Search the product catalog.",
54
+ params: { query: "string" },
55
+ handler: async ({ query }) => ({
56
+ query,
57
+ items: await searchProducts(query)
58
+ })
59
+ }
60
+ }
61
+ }));
62
+ ```
63
+
64
+ Follow the [Express quickstart in the AgentsBloom documentation](https://docs.agentsbloom.com). You do not need to rewrite your storefront or move your commerce logic into a proprietary platform.
65
+
66
+ ## What the SDK provides
67
+
68
+ - Action discovery and machine-readable commerce metadata.
69
+ - Express middleware for agent-facing store actions.
70
+ - UCP, ACP, AP2, WebMCP, and Web Bot Auth building blocks.
71
+ - RFC 9421-compatible HTTP Message Signature verification.
72
+ - Legacy HMAC signatures with timestamp and nonce replay protection.
73
+ - AP2 mandate creation and verification with budget, audience, lifetime, category, and replay checks.
74
+ - Per-IP rate limiting and idempotency handling for protected writes.
75
+ - Optional OpenTelemetry export with graceful fallback when exporters are unavailable.
76
+ - HTML metadata and WebMCP injection for compatible responses.
77
+
78
+ ## Authentication paths
79
+
80
+ The SDK does not require an AgentsBloom account just to install or self-host the middleware. Choose the authentication model that fits your integration:
81
+
82
+ - **Legacy HMAC writes:** configure a private merchant-generated `AGENTSBLOOM_SECRET` or `agentSecret`. This is required only for requests using the legacy `X-Agent-Signature` headers.
83
+ - **RFC HTTP Message Signatures:** configure trusted agent public keys through `agentJwks` or `agentJwksUrl`; this path does not use `AGENTSBLOOM_SECRET`.
84
+ - **AP2:** use the package's signed mandate helpers and verification path.
85
+ - **Local demos:** `demoMode` can bypass signature authentication, but it must never be enabled for an internet-facing production deployment.
86
+
87
+ An `AGENTSBLOOM_API_KEY` is a separate account/service-integration value. It is not the HMAC signing secret. Keep both values server-side and out of source control.
88
+
89
+ ## Requirements
90
+
91
+ - Node.js 20 or newer.
92
+ - An Express 4 application.
93
+ - A real `AGENTSBLOOM_SECRET` for protected legacy-signed write actions, or a configured RFC Message Signature trust path.
94
+
95
+ ## Minimal production setup
96
+
97
+ ```js
98
+ import express from "express";
99
+ import { agentsbloom, shutdown } from "@agentsbloom/sdk";
100
+
101
+ const app = express();
102
+ const agentSecret = process.env.AGENTSBLOOM_SECRET;
103
+
104
+ if (!agentSecret) {
105
+ throw new Error("AGENTSBLOOM_SECRET must be configured for legacy-signed writes");
106
+ }
107
+
108
+ app.use(express.json({ limit: "1mb" }));
109
+ app.use(agentsbloom({
110
+ apiKey: process.env.AGENTSBLOOM_API_KEY,
111
+ agentSecret,
112
+ baseUrl: process.env.PUBLIC_STORE_URL,
113
+ name: "Example Store",
114
+ description: "An example store for agent-driven commerce.",
115
+ actions: {
116
+ search: {
117
+ method: "POST",
118
+ description: "Search the product catalog.",
119
+ params: { query: "string" },
120
+ handler: async ({ query }) => ({ query, items: [] })
121
+ }
122
+ }
123
+ }));
124
+
125
+ const server = app.listen(process.env.PORT || 3000);
126
+ const closeServer = () => new Promise((resolve, reject) => {
127
+ if (!server.listening) return resolve();
128
+ server.close((error) => error ? reject(error) : resolve());
129
+ });
130
+ const stop = async () => {
131
+ try {
132
+ await closeServer();
133
+ } finally {
134
+ await shutdown();
135
+ }
136
+ };
137
+ process.once("SIGTERM", stop);
138
+ process.once("SIGINT", stop);
139
+ ```
140
+
141
+ `baseUrl` should be the canonical public HTTPS origin of the store. Do not put API keys or signing secrets in source control, client-side code, logs, or package metadata.
142
+
143
+ ## Configuration
144
+
145
+ - `apiKey`: optional AgentsBloom account key used for attribution and service integrations.
146
+ - `agentSecret`: secret used to verify legacy `X-Agent-Identifier`/`X-Agent-Signature` requests. If omitted, `AGENTSBLOOM_SECRET` is read from the environment; if neither is set, legacy signed writes fail closed.
147
+ - `baseUrl`: canonical store origin used for discovery and audience binding.
148
+ - `actions`: map of agent action names to handlers. Handlers receive `(params, req, res)` and may return a value or a promise. `method` defaults to `POST`; declare `method: "GET"` explicitly for a read action.
149
+ - `rateLimit`: optional `{ max, windowMs }` in-memory per-IP limits.
150
+ - `idempotency`: optional `{ ttlMs }` for successful write responses keyed by `Idempotency-Key`.
151
+ - `ap2`: optional AP2 settings including `expectedAudience`, `maxMandateLifetimeSec`, `requireJti`, and `requestedCategories`.
152
+ - `merchantJwks`: merchant JWKS document served at the HTTP Message Signatures discovery endpoint.
153
+ - `agentJwks`: optional inline trusted JWKS used to verify RFC HTTP Message Signatures.
154
+ - `agentJwksUrl`: optional HTTPS URL for the trusted agent JWKS. A request cannot select an arbitrary remote JWKS URL.
155
+ - `signature`: optional `{ maxAgeMs }` for legacy HMAC timestamp validation; the default is five minutes.
156
+ - `demoMode`: explicit local/demo-only bypass for signature authentication. Never enable it in production.
157
+ - `disableSignatureAuth`: explicit compatibility bypass. Do not enable it for an internet-facing deployment.
158
+
159
+ The middleware does not replace application-level authorization, a distributed rate limiter, a durable idempotency store, TLS termination, or payment-provider verification.
160
+
161
+ ## Legacy HMAC request signatures
162
+
163
+ For a mutating action using `X-Agent-Signature`, send:
164
+
165
+ - `X-Agent-Identifier`: printable agent identifier.
166
+ - `X-Agent-Timestamp`: current Unix timestamp in seconds.
167
+ - `X-Agent-Nonce`: unique printable nonce of at least 16 characters.
168
+ - `X-Agent-Signature`: lowercase or uppercase hexadecimal HMAC-SHA-256.
169
+
170
+ The signed payload is the JSON array `[identifier, method, originalUrl, timestamp, nonce, parsedBody]`, using the configured `agentSecret`. Signatures expire after five minutes by default and a nonce cannot be consumed twice by the same identifier within the process. Identifier-only signatures from older SDK revisions are intentionally rejected.
171
+
172
+ ## RFC HTTP Message Signatures
173
+
174
+ Protected writes using the RFC 9421-compatible path must sign `@method`, `@path`, and `content-digest`, and include `created`, `expires`, `nonce`, `keyid`, and `alg` parameters. The SDK validates the lifetime, rejects reused nonces, and recomputes `content-digest` from `req.rawBody` when present or the parsed request body otherwise.
175
+
176
+ ## MCP message authentication
177
+
178
+ The SSE connection at `/mcp` can advertise configured tools, but mutating MCP messages sent to `/mcp/messages` must pass the same configured RFC HTTP Message Signature or legacy `X-Agent-Signature` verification as other protected writes.
179
+
180
+ ## AP2
181
+
182
+ The package exports helpers for creating and verifying signed AP2 mandates:
183
+
184
+ ```js
185
+ import {
186
+ createAp2Mandate,
187
+ verifyAP2Mandates,
188
+ resetAp2ReplayCache
189
+ } from "@agentsbloom/sdk";
190
+
191
+ const { token } = createAp2Mandate({
192
+ audience: "https://store.example",
193
+ maxBudget: 100
194
+ });
195
+
196
+ const result = verifyAP2Mandates(
197
+ { "x-ap2-mandate": `Bearer ${token}` },
198
+ { orderTotal: 40 },
199
+ { expectedAudience: "https://store.example" }
200
+ );
201
+
202
+ if (!result.valid) {
203
+ throw new Error(result.reason);
204
+ }
205
+ ```
206
+
207
+ Presented mandates are cryptographically verified. The verifier enforces signature algorithms, issuer/audience binding, bounded lifetime, required `jti` replay protection, optional category restrictions, and budget limits.
208
+
209
+ ## Telemetry
210
+
211
+ `setupTelemetry()` dynamically loads the optional OpenTelemetry packages and continues without an exporter when they are unavailable. `shutdown()` closes the configured provider and clears SDK in-memory state.
212
+
213
+ ```js
214
+ import { setupTelemetry } from "@agentsbloom/sdk";
215
+
216
+ await setupTelemetry({
217
+ otlpEndpoint: process.env.AGENTSBLOOM_OTEL_ENDPOINT,
218
+ serviceName: "example-store",
219
+ samplingRatio: 1,
220
+ apiKey: process.env.AGENTSBLOOM_API_KEY
221
+ });
222
+ ```
223
+
224
+ ## Learn more
225
+
226
+ - [AgentsBloom documentation](https://docs.agentsbloom.com)
227
+ - [AgentsBloom marketing site](https://agentsbloom.com)
228
+ - [AgentsBloom blog](https://blog.agentsbloom.com)
229
+ - [AgentsBloom organization](https://github.com/AgentsBloom)
230
+ - [SDK issues and discussions](https://github.com/AgentsBloom/sdk/issues)
231
+
232
+ ## Development and release checks
233
+
234
+ From this package directory:
235
+
236
+ ```sh
237
+ npm ci
238
+ npm test
239
+ npm run lint
240
+ npm run check:package
241
+ npm run verify:consumer
242
+ npm run release:check
243
+ npm pack --dry-run --ignore-scripts
244
+ ```
245
+
246
+ The package uses an explicit npm `files` allowlist. Tests and release scripts remain in the repository but are intentionally excluded from the published tarball. These commands do not publish to npm.
247
+
248
+ ## Security
249
+
250
+ Please report suspected vulnerabilities privately. See [`SECURITY.md`](./SECURITY.md). Never include live credentials in an issue, pull request, test fixture, or support request.
251
+
252
+ ## License
253
+
254
+ MIT. See [`LICENSE`](./LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,19 @@
1
+ # Security policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ Please report suspected vulnerabilities privately to `contact@agentsbloom.com` with the subject `AgentsBloom SDK security report`. Include the affected package version, a concise reproduction, and the impact. Do not include live API keys, payment credentials, signing secrets, personal data, or private repository URLs in the report.
6
+
7
+ We will acknowledge a report when practical, investigate it privately, and coordinate a fix and disclosure timeline with the reporter. Please do not disclose an unpatched vulnerability in a public issue or pull request.
8
+
9
+ ## Supported versions
10
+
11
+ The latest published version is the primary supported version. Security fixes may not be backported to end-of-life versions.
12
+
13
+ ## Deployment guidance
14
+
15
+ - Configure a unique high-entropy `AGENTSBLOOM_SECRET` for every merchant deployment.
16
+ - Keep secrets in the deployment secret manager or environment, never in source control or browser bundles.
17
+ - Do not use `demoMode` or `disableSignatureAuth` for internet-facing production traffic.
18
+ - Use HTTPS, durable authorization, and a distributed rate/idempotency store for production systems.
19
+ - Rotate any credential that has appeared in logs, chat, tickets, shell history, or a repository.
@@ -0,0 +1,25 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-labelledby="agentsbloom-title">
2
+ <title id="agentsbloom-title">AgentsBloom</title>
3
+ <style>
4
+ @media (prefers-color-scheme: dark) {
5
+ .s1 { stop-color: #4A90F7; }
6
+ .s2 { stop-color: #4EE2F8; }
7
+ .s3 { stop-color: #C3AFFF; }
8
+ }
9
+ </style>
10
+ <defs>
11
+ <linearGradient id="lotus-gradient" x1="0" y1="0" x2="1" y2="1">
12
+ <stop class="s1" offset="0%" stop-color="#1A73E8" />
13
+ <stop class="s2" offset="50%" stop-color="#22D3EE" />
14
+ <stop class="s3" offset="100%" stop-color="#A78BFA" />
15
+ </linearGradient>
16
+ </defs>
17
+ <g fill="url(#lotus-gradient)">
18
+ <path d="M32 52c1.6 2 2.7 3.7 3.3 5.2.2.6 0 1-.6 1.3l-2.7 1.5-2.7-1.5c-.6-.3-.8-.7-.6-1.3.6-1.5 1.7-3.2 3.3-5.2z" />
19
+ <path d="M14.5 20.8c.2-1 .7-1.2 1.6-.8 4.5 1.9 8 4.8 10.5 8.7 2.3 3.6 3.6 7.7 3.8 12.2 0 1-.4 1.4-1.3 1.1-4.7-1.5-8.4-4.3-11.1-8.4-2.6-4-3.8-8.3-3.5-12.8z" />
20
+ <path d="M49.5 20.8c-.2-1-.7-1.2-1.6-.8-4.5 1.9-8 4.8-10.5 8.7-2.3 3.6-3.6 7.7-3.8 12.2 0 1 .4 1.4 1.3 1.1 4.7-1.5 8.4-4.3 11.1-8.4 2.6-4 3.8-8.3 3.5-12.8z" />
21
+ <path d="M4 30c0-1 .3-1.5 1.3-1.6 6.5-.5 12.5 1.2 17.6 4.8 4.6 3.3 7.7 7.8 9.3 13.2.3 1 .1 1.6-.9 1.7-6.8.8-13-.7-18.4-4.6C7.5 39.6 4.3 34.9 4 30z" />
22
+ <path d="M60 30c0-1-.3-1.5-1.3-1.6-6.5-.5-12.5 1.2-17.6 4.8-4.6 3.3-7.7 7.8-9.3 13.2-.3 1-.1 1.6.9 1.7 6.8.8 13-.7 18.4-4.6C56.5 39.6 59.7 34.9 60 30z" />
23
+ <path d="M32 6c4.5 6 7.2 12 8 18 .8 6-.5 12-4 18l-4 6-4-6c-3.5-6-4.8-12-4-18 .8-6 3.5-12 8-18z" />
24
+ </g>
25
+ </svg>
package/index.d.ts ADDED
@@ -0,0 +1,124 @@
1
+ export type Protocol = 'WEBMCP' | 'UCP' | 'ACP' | 'AP2' | 'AGENTSBLOOM_REST';
2
+
3
+ export type AgentActionHandler = (
4
+ params: Record<string, unknown>,
5
+ req: unknown,
6
+ res: unknown
7
+ ) => unknown | Promise<unknown>;
8
+
9
+ export interface AgentAction {
10
+ method?: string;
11
+ description?: string;
12
+ params?: Record<string, string>;
13
+ handler: AgentActionHandler;
14
+ }
15
+
16
+ export interface AgentsBloomConfig {
17
+ apiKey?: string | null;
18
+ agentSecret?: string | null;
19
+ name?: string;
20
+ description?: string;
21
+ actions?: Record<string, AgentAction>;
22
+ llmsDoc?: string;
23
+ baseUrl?: string;
24
+ corsOrigin?: string;
25
+ merchantJwks?: Record<string, unknown>;
26
+ agentJwks?: {
27
+ keys: Array<Record<string, unknown>>;
28
+ };
29
+ agentJwksUrl?: string;
30
+ signature?: {
31
+ maxAgeMs?: number;
32
+ };
33
+ ap2PublicKey?: unknown;
34
+ ap2?: {
35
+ expectedAudience?: string;
36
+ maxMandateLifetimeSec?: number;
37
+ requireJti?: boolean;
38
+ requestedCategories?: string[];
39
+ };
40
+ rateLimit?: {
41
+ max?: number;
42
+ windowMs?: number;
43
+ };
44
+ idempotency?: {
45
+ ttlMs?: number;
46
+ };
47
+ demoMode?: boolean;
48
+ disableSignatureAuth?: boolean;
49
+ disableHtmlInjection?: boolean;
50
+ }
51
+
52
+ export type AgentsBloomMiddleware = (
53
+ req: unknown,
54
+ res: unknown,
55
+ next: (error?: unknown) => void
56
+ ) => unknown;
57
+
58
+ export interface TelemetryOptions {
59
+ otlpEndpoint?: string;
60
+ serviceName?: string;
61
+ samplingRatio?: number;
62
+ apiKey?: string;
63
+ }
64
+
65
+ export interface TelemetryConfig {
66
+ otlpEndpoint: string;
67
+ serviceName: string;
68
+ samplingRatio: number;
69
+ }
70
+
71
+ export interface Ap2VerificationResult {
72
+ valid: boolean;
73
+ verified?: boolean;
74
+ protocol: 'AP2';
75
+ reason?: string;
76
+ note?: string;
77
+ selfCertifying?: boolean;
78
+ mandates?: Record<string, unknown>;
79
+ }
80
+
81
+ export interface Ap2VerifyOptions {
82
+ trustedPublicKey?: unknown;
83
+ expectedAudience?: string;
84
+ maxMandateLifetimeSec?: number;
85
+ requireJti?: boolean;
86
+ requestedCategories?: string[];
87
+ }
88
+
89
+ export interface CreateAp2MandateOptions {
90
+ audience: string;
91
+ maxBudget: number;
92
+ currency?: string;
93
+ allowedCategories?: string[];
94
+ merchantScope?: string;
95
+ lifetimeSec?: number;
96
+ paymentMethod?: string;
97
+ subject?: string;
98
+ privateKey?: unknown;
99
+ }
100
+
101
+ export interface Ap2Mandate {
102
+ token: string;
103
+ did: string;
104
+ publicKey: unknown;
105
+ privateKey: unknown;
106
+ }
107
+
108
+ export function agentsbloom(config?: AgentsBloomConfig): AgentsBloomMiddleware;
109
+ export function setupTelemetry(options?: TelemetryOptions): Promise<TelemetryConfig>;
110
+ export function shutdown(): Promise<void>;
111
+ export function resolveProtocol(req: {
112
+ headers?: Record<string, string | undefined>;
113
+ path?: string;
114
+ url?: string;
115
+ }): Protocol;
116
+ export function verifyAP2Mandates(
117
+ headers?: Record<string, string | undefined>,
118
+ body?: Record<string, unknown>,
119
+ publicKeyOrOptions?: unknown | Ap2VerifyOptions
120
+ ): Ap2VerificationResult;
121
+ export function createAp2Mandate(options: CreateAp2MandateOptions): Ap2Mandate;
122
+ export function didKeyFromEd25519PublicKey(publicKey: unknown): string;
123
+ export function ed25519PublicKeyFromDidKey(didKey: string): unknown | null;
124
+ export function resetAp2ReplayCache(): void;