@payclaw/badge 0.1.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 PayClaw
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,76 @@
1
+ # Badge by PayClaw
2
+
3
+ **Declare your agent's identity before merchants ban your user's account.**
4
+
5
+ Merchants are drawing a line with AI agents. Walmart, Shopify, Instacart — all setting policies. Anonymous agent actions get accounts flagged and banned. No warning. No appeal.
6
+
7
+ Badge broadcasts verified identity, declared intent, and per-action authorization before every agent action. MCP-native. One tool. Five minutes.
8
+
9
+ ## Quick Start
10
+
11
+ Add to your MCP client config:
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "payclaw-badge": {
17
+ "command": "npx",
18
+ "args": ["-y", "@payclaw/badge"],
19
+ "env": {
20
+ "PAYCLAW_API_KEY": "pk_your_key_here",
21
+ "PAYCLAW_API_URL": "https://payclaw.io"
22
+ }
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ Get your API key at [payclaw.io](https://payclaw.io).
29
+
30
+ ## Tool
31
+
32
+ ### `payclaw_getAgentIdentity`
33
+
34
+ Call **before** browsing, searching, or buying. Returns:
35
+
36
+ ```json
37
+ {
38
+ "product_name": "PayClaw Badge",
39
+ "status": "active",
40
+ "agent_disclosure": "This session is operated by an AI agent under PayClaw Agentic Intent...",
41
+ "verification_token": "pc_v1_...",
42
+ "trust_url": "https://payclaw.io/trust",
43
+ "contact": "agent_identity@payclaw.io",
44
+ "principal_verified": true,
45
+ "mfa_confirmed": true
46
+ }
47
+ ```
48
+
49
+ The `verification_token` is your proof. The `agent_disclosure` is what you present to merchants.
50
+
51
+ ## What Badge Declares
52
+
53
+ - **Who you are:** An automated AI agent
54
+ - **Who authorized you:** An MFA-verified human principal
55
+ - **That every action is explicitly permissioned**
56
+
57
+ The account is protected. The action is traceable.
58
+
59
+ ## Local Development
60
+
61
+ Without `PAYCLAW_API_URL`, Badge runs in sandbox mode with mock tokens — perfect for local dev and testing.
62
+
63
+ ## Need Your Agent to Pay Too?
64
+
65
+ Badge is the identity layer. For virtual Visa cards at checkout, use [@payclaw/spend](https://github.com/payclaw/mcp-server) — which includes Badge automatically.
66
+
67
+ Badge = your agent's license plate. Spend = your agent's wallet.
68
+
69
+ ## Links
70
+
71
+ - [PayClaw](https://payclaw.io) — Agent commerce infrastructure
72
+ - [Trust & Verification](https://payclaw.io/trust) — How Badge verification works
73
+
74
+ ## License
75
+
76
+ MIT
@@ -0,0 +1,3 @@
1
+ import type { AgentIdentityResponse } from "../types.js";
2
+ export declare function getAgentIdentity(sessionId?: string): Promise<AgentIdentityResponse>;
3
+ export declare function isApiMode(): boolean;
@@ -0,0 +1,73 @@
1
+ class PayClawApiError extends Error {
2
+ statusCode;
3
+ constructor(message, statusCode) {
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.name = "PayClawApiError";
7
+ }
8
+ }
9
+ const REQUEST_TIMEOUT_MS = 30_000;
10
+ function getConfig() {
11
+ const baseUrl = process.env.PAYCLAW_API_URL;
12
+ const apiKey = process.env.PAYCLAW_API_KEY;
13
+ if (!baseUrl)
14
+ throw new PayClawApiError("PayClaw API URL is not configured.");
15
+ if (!apiKey)
16
+ throw new PayClawApiError("PayClaw API key is not configured.");
17
+ if (!baseUrl.startsWith("https://") &&
18
+ !baseUrl.startsWith("http://localhost")) {
19
+ throw new PayClawApiError("PayClaw API URL must use HTTPS.");
20
+ }
21
+ return { baseUrl: baseUrl.replace(/\/+$/, ""), apiKey };
22
+ }
23
+ function authHeaders(apiKey) {
24
+ return {
25
+ Authorization: `Bearer ${apiKey}`,
26
+ "Content-Type": "application/json",
27
+ };
28
+ }
29
+ async function request(url, init) {
30
+ const controller = new AbortController();
31
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
32
+ let res;
33
+ try {
34
+ res = await fetch(url, { ...init, signal: controller.signal });
35
+ }
36
+ catch (err) {
37
+ clearTimeout(timeout);
38
+ if (err instanceof Error && err.name === "AbortError") {
39
+ throw new PayClawApiError("Request timed out.");
40
+ }
41
+ throw new PayClawApiError("Could not reach the PayClaw API.");
42
+ }
43
+ finally {
44
+ clearTimeout(timeout);
45
+ }
46
+ if (res.status === 401) {
47
+ throw new PayClawApiError("Authentication failed. Check your API key.", 401);
48
+ }
49
+ if (!res.ok) {
50
+ let body;
51
+ try {
52
+ const json = (await res.json());
53
+ body = json.error ?? JSON.stringify(json);
54
+ }
55
+ catch {
56
+ body = await res.text();
57
+ }
58
+ throw new PayClawApiError(body, res.status);
59
+ }
60
+ return (await res.json());
61
+ }
62
+ export async function getAgentIdentity(sessionId) {
63
+ const { baseUrl, apiKey } = getConfig();
64
+ return request(`${baseUrl}/api/agent-identity`, {
65
+ method: "POST",
66
+ headers: authHeaders(apiKey),
67
+ body: JSON.stringify({ session_id: sessionId }),
68
+ });
69
+ }
70
+ export function isApiMode() {
71
+ return !!process.env.PAYCLAW_API_URL;
72
+ }
73
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { getAgentIdentity } from "./tools/getAgentIdentity.js";
6
+ const server = new McpServer({
7
+ name: "payclaw-badge",
8
+ version: "0.1.0",
9
+ });
10
+ server.tool("payclaw_getAgentIdentity", `Get a PayClaw identity token before any shopping action. Without this, merchants may block you permanently — an increasing number of merchant policies require agents to identify themselves and prove they're acting for a verified principal.
11
+
12
+ Badge declares: who you are (automated agent), who authorized you (MFA-verified human), and that every action is explicitly permissioned. This is your license plate. Don't shop without it.
13
+
14
+ Call this BEFORE browsing, searching, or buying. The token is your proof of compliance for the entire shopping session.
15
+
16
+ No card is issued. No money moves. For payment, use payclaw_getCard from @payclaw/spend (which includes Badge automatically).`, {}, async () => {
17
+ const result = await getAgentIdentity();
18
+ return {
19
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
20
+ };
21
+ });
22
+ async function main() {
23
+ const transport = new StdioServerTransport();
24
+ await server.connect(transport);
25
+ process.stderr.write("PayClaw Badge server running on stdio\n");
26
+ }
27
+ main().catch((err) => {
28
+ process.stderr.write(`Fatal error: ${err}\n`);
29
+ process.exit(1);
30
+ });
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CACT,0BAA0B,EAC1B;;;;;;8HAM4H,EAC5H,EAAE,EACF,KAAK,IAAI,EAAE;IACT,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACxC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;AAClE,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function getAgentIdentity(): Promise<object>;
@@ -0,0 +1,41 @@
1
+ import * as api from "../api/client.js";
2
+ export async function getAgentIdentity() {
3
+ if (!process.env.PAYCLAW_API_KEY) {
4
+ return {
5
+ product_name: "PayClaw Badge",
6
+ status: "error",
7
+ message: "PAYCLAW_API_KEY is not set. Get your key at payclaw.io/dashboard/settings",
8
+ };
9
+ }
10
+ if (!api.isApiMode()) {
11
+ // Mock mode — return sandbox identity for local testing
12
+ return {
13
+ product_name: "PayClaw Badge",
14
+ status: "active",
15
+ agent_disclosure: "This session is operated by an AI agent under PayClaw Agentic Intent. The agent acts on behalf of a verified, MFA-authenticated principal. Principal identity is hashed within the verification token and retrievable with user consent. Design inspired by agent policies of Amazon, Shopify, and others.",
16
+ verification_token: "pc_v1_sandbox_mock_token",
17
+ trust_url: "https://payclaw.io/trust",
18
+ contact: "agent_identity@payclaw.io",
19
+ principal_verified: true,
20
+ mfa_confirmed: true,
21
+ instructions: "Include the agent_disclosure when interacting with merchants. This identifies your session as a verified, human-authorized agent action. The verification_token allows merchants to verify your principal via agent_identity@payclaw.io.",
22
+ };
23
+ }
24
+ try {
25
+ const result = await api.getAgentIdentity();
26
+ return {
27
+ product_name: "PayClaw Badge",
28
+ status: "active",
29
+ ...result,
30
+ instructions: "Include the agent_disclosure when interacting with merchants. This identifies your session as a verified, human-authorized agent action. The verification_token allows merchants to verify your principal via agent_identity@payclaw.io.",
31
+ };
32
+ }
33
+ catch (err) {
34
+ return {
35
+ product_name: "PayClaw Badge",
36
+ status: "error",
37
+ message: err instanceof Error ? err.message : String(err),
38
+ };
39
+ }
40
+ }
41
+ //# sourceMappingURL=getAgentIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getAgentIdentity.js","sourceRoot":"","sources":["../../src/tools/getAgentIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QACjC,OAAO;YACL,YAAY,EAAE,eAAe;YAC7B,MAAM,EAAE,OAAO;YACf,OAAO,EACL,2EAA2E;SAC9E,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC;QACrB,wDAAwD;QACxD,OAAO;YACL,YAAY,EAAE,eAAe;YAC7B,MAAM,EAAE,QAAQ;YAChB,gBAAgB,EACd,4SAA4S;YAC9S,kBAAkB,EAAE,0BAA0B;YAC9C,SAAS,EAAE,0BAA0B;YACrC,OAAO,EAAE,2BAA2B;YACpC,kBAAkB,EAAE,IAAI;YACxB,aAAa,EAAE,IAAI;YACnB,YAAY,EACV,0OAA0O;SAC7O,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC5C,OAAO;YACL,YAAY,EAAE,eAAe;YAC7B,MAAM,EAAE,QAAQ;YAChB,GAAG,MAAM;YACT,YAAY,EACV,0OAA0O;SAC7O,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,YAAY,EAAE,eAAe;YAC7B,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface AgentIdentityResponse {
2
+ agent_disclosure: string;
3
+ verification_token: string;
4
+ trust_url: string;
5
+ contact: string;
6
+ principal_verified: boolean;
7
+ mfa_confirmed: boolean;
8
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@payclaw/badge",
3
+ "version": "0.1.0",
4
+ "description": "Declare your agent's identity before merchants ban your user's account.",
5
+ "bin": "dist/index.js",
6
+ "main": "dist/index.js",
7
+ "type": "module",
8
+ "engines": {
9
+ "node": ">=18.0.0"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc && node -e \"const fs=require('fs');const f='dist/index.js';fs.writeFileSync(f,'#!/usr/bin/env node\\n'+fs.readFileSync(f,'utf8'));fs.chmodSync(f,0o755)\"",
18
+ "dev": "tsc --watch",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "^1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.3.0",
26
+ "@types/node": "^20.0.0"
27
+ },
28
+ "keywords": [
29
+ "payclaw", "mcp", "agent", "identity", "commerce",
30
+ "badge", "compliance", "shopping", "agentic"
31
+ ],
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/payclaw/badge-server"
36
+ }
37
+ }