Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .cursor-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "agent-commerce",
"owner": { "name": "devlab-group" },
"metadata": { "description": "The Agent Commerce Gateway skill for coding agents." },
"plugins": [
{
"name": "agent-commerce-gateway",
"source": "./plugins/agent-commerce-gateway",
"description": "Integrate the Agent Commerce Gateway into an existing HTTP API: configure, start and verify it."
}
]
}
15 changes: 15 additions & 0 deletions plugins/agent-commerce-gateway/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "agent-commerce-gateway",
"displayName": "Agent Commerce Gateway",
"version": "2.7.2",
"description": "Put the Agent Commerce Gateway in front of an existing HTTP API so AI agents can call and pay for it with x402.",
"author": { "name": "devlab-group" },
"homepage": "https://github.com/devlab-group/agent-commerce#readme",
"repository": "https://github.com/devlab-group/agent-commerce",
"license": "Apache-2.0",
"logo": ".claude-plugin/icon.png",
"keywords": ["x402", "mcp", "ai-agents", "payments", "agentic-commerce"],
"category": "developer-tools",
"tags": ["x402", "payments", "mcp"],
"skills": "./skills/"
}
4 changes: 2 additions & 2 deletions plugins/agent-commerce-gateway/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agent Commerce Gateway plugin

This plugin adds one skill, `agent-commerce`, that helps Claude put
This plugin adds one skill, `agent-commerce`, that helps a coding agent put
[Agent Commerce Gateway](https://github.com/devlab-group/agent-commerce)
(npm `@devlab.group/agent-commerce`) in front of an existing HTTP API. AI
agents can then call the API's endpoints over HTTP or MCP and pay for them
Expand Down Expand Up @@ -37,7 +37,7 @@ anywhere.
## Credentials the gateway uses

The skill writes credentials only as `${VAR}` placeholders in the gateway's
`config.yaml`, and tells Claude never to ask for a secret in chat or write one
`config.yaml`, and tells the agent never to ask for a secret in chat or write one
into a file, command or log. The user sets the values in the gateway's own
`.env`, which the gateway CLI reads when it runs. Each value goes only to the
party it belongs to:
Expand Down
6 changes: 5 additions & 1 deletion scripts/check-package-metadata.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
/**
* Require package and Claude Code plugin links to point at the real repository.
* Require package, Claude Code plugin and Cursor plugin links to point at the real repository.
* A wrong namespace could send private vulnerability reports to an attacker.
* An allowlist rejects destinations a placeholder blocklist would miss.
*/
Expand All @@ -13,6 +13,8 @@ const manifestPath = resolve(root, 'package.json');
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
const pluginManifest = 'plugins/agent-commerce-gateway/.claude-plugin/plugin.json';
const plugin = JSON.parse(readFileSync(resolve(root, pluginManifest), 'utf8'));
const cursorManifest = 'plugins/agent-commerce-gateway/.cursor-plugin/plugin.json';
const cursor = JSON.parse(readFileSync(resolve(root, cursorManifest), 'utf8'));

const EXPECTED = 'github.com/devlab-group/agent-commerce';

Expand All @@ -24,6 +26,8 @@ const fields = [
[`${pluginManifest} homepage`, plugin.homepage],
[`${pluginManifest} documentationUrl`, plugin.documentationUrl],
[`${pluginManifest} supportUrl`, plugin.supportUrl],
[`${cursorManifest} repository`, cursor.repository],
[`${cursorManifest} homepage`, cursor.homepage],
];

// Anchored at the scheme and host, because npm renders these as links: a
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/cli/skill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,46 @@ describe('Claude Code plugin', () => {
expect(existsSync(join(pluginDir, 'package.json'))).toBe(false);
});
});

describe('Cursor plugin', () => {
const plugin = readJson<{
name: string;
displayName: string;
version: string;
description: string;
license: string;
logo: string;
skills: string;
}>(join(pluginDir, '.cursor-plugin', 'plugin.json'));
const claude = readJson<{ name: string; displayName: string; description: string }>(
join(pluginDir, '.claude-plugin', 'plugin.json'),
);
const marketplace = readJson<{ name: string; plugins: { name: string; source: string }[] }>(
join(root, '.cursor-plugin', 'marketplace.json'),
);

it('releases with the package version and matches the Claude Code plugin', () => {
expect(plugin.version).toBe(manifest.version);
expect(plugin.license).toBe(manifest.license);
expect(plugin).toMatchObject({
name: claude.name,
displayName: claude.displayName,
description: claude.description,
});
});

it('is listed in the marketplace from the same folder', () => {
expect(marketplace.plugins).toEqual([
expect.objectContaining({ name: plugin.name, source: './plugins/agent-commerce-gateway' }),
]);
});

it('points at files inside the plugin folder', () => {
// Cursor requires relative manifest paths without `..`
for (const path of [plugin.logo, plugin.skills]) {
expect(path).not.toMatch(/^\/|^[a-z]+:|\.\./);
expect(existsSync(join(pluginDir, path))).toBe(true);
}
expect(existsSync(join(pluginDir, plugin.skills, 'agent-commerce', 'SKILL.md'))).toBe(true);
});
});
Loading