ai-supply-mcp 1.0.1 → 1.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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/package.json +26 -6
  3. package/server.mjs +11 -20
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # ai-supply-mcp
2
2
 
3
- MCP server for **[ai-supply.store](https://ai-supply.store)** — the security-scanned marketplace for AI capabilities. Connect it to any MCP client (Claude Code, Claude Desktop, VS Code / GitHub Copilot, Cursor) and your agent can **search, install, download, publish, version, and review** capabilities natively — full parity with the website.
3
+ MCP server for **[ai-supply.store](https://ai-supply.store)** — the free, security-vetted registry of AI capabilities. Every capability is downloaded, scanned, and graded **0–100 (A–D)** for security before it's listed; risky ones are hidden by default. Connect it to any MCP client (Claude Code, Claude Desktop, VS Code / GitHub Copilot, Cursor) and your agent can **search, install, download, publish, version, and review** capabilities natively — full parity with the website, and every search result carries its security score.
4
4
 
5
5
  ## 1. Get an API key
6
6
 
7
- Create one at **https://ai-supply.store/dashboard/api-keys** and pick the scopes the agent needs (`read`, `install`, `purchase`, `publish`, `review`, `manage`, `account`). The server mints a short-lived, revocable agent **session** from your key on startup, so the long-lived key isn't sent on every request.
7
+ Create one at **https://ai-supply.store/dashboard/api-keys** and pick the scopes the agent needs (`read`, `install`, `publish`, `review`, `manage`, `account`). The `read` scope alone is enough to browse the vetted catalog. The server mints a short-lived, revocable agent **session** from your key on startup, so the long-lived key isn't sent on every request.
8
8
 
9
9
  ## 2. Add it to your client
10
10
 
@@ -32,11 +32,11 @@ claude mcp add ai-supply --env AIM_API_KEY=aim_your_key_here -- npx -y ai-supply
32
32
 
33
33
  > VS Code / Copilot also discover this server from the MCP Registry — search `@mcp ai-supply` in the Extensions view.
34
34
 
35
- ## Tools (19)
35
+ ## Tools (17)
36
36
 
37
- `whoami`, `list_categories`, `list_kinds`, `search_listings`, `get_listing`, `install_listing`, `purchase_listing`, `download_listing`, `review_listing`, `upload_artifact`, `publish_listing`, `update_listing`, `delete_listing`, `add_version`, `my_listings`, `list_community`, `post_community`, `accept_agreements`, `my_revenue`.
37
+ `whoami`, `list_categories`, `list_kinds`, `search_listings`, `get_listing`, `install_listing`, `download_listing`, `review_listing`, `upload_artifact`, `publish_listing`, `update_listing`, `delete_listing`, `add_version`, `my_listings`, `list_community`, `post_community`, `accept_agreements`.
38
38
 
39
- Each tool calls the corresponding `/api/v1` endpoint and is gated by the credential's scopes (and spend cap for purchases). Every capability on ai-supply is security-scanned, scored, and graded before it's published.
39
+ Each tool calls the corresponding `/api/v1` endpoint and is gated by the credential's scopes. Every capability on ai-supply is security-scanned and graded (0–100 score, A–D grade) before it's listed — `search_listings` supports `sort: "security"` to rank the most-secure first, `get_listing` returns the full scan findings, and quarantined (critical-finding) listings are hidden by default. The whole catalog is **free**. See <https://ai-supply.store/security> for the vetting methodology.
40
40
 
41
41
  ## Local development
42
42
 
package/package.json CHANGED
@@ -1,16 +1,36 @@
1
1
  {
2
2
  "name": "ai-supply-mcp",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
- "bin": { "ai-supply-mcp": "./server.mjs" },
5
+ "bin": {
6
+ "ai-supply-mcp": "./server.mjs"
7
+ },
6
8
  "description": "MCP server for ai-supply.store — search, install, download, publish and review security-scanned AI capabilities from any MCP client (Claude, VS Code/Copilot, Cursor).",
7
9
  "mcpName": "io.github.ai-supply-store/ai-supply",
8
10
  "homepage": "https://ai-supply.store",
9
- "repository": { "type": "git", "url": "git+https://github.com/ai-supply-store/ai-supply-plugin.git", "directory": "mcp" },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/ai-supply-store/ai-supply-plugin.git",
14
+ "directory": "mcp"
15
+ },
10
16
  "license": "MIT",
11
- "keywords": ["mcp", "modelcontextprotocol", "ai-supply", "marketplace", "ai-agents", "claude", "copilot"],
12
- "files": ["server.mjs", "lib.mjs", "README.md"],
13
- "engines": { "node": ">=18" },
17
+ "keywords": [
18
+ "mcp",
19
+ "modelcontextprotocol",
20
+ "ai-supply",
21
+ "marketplace",
22
+ "ai-agents",
23
+ "claude",
24
+ "copilot"
25
+ ],
26
+ "files": [
27
+ "server.mjs",
28
+ "lib.mjs",
29
+ "README.md"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
14
34
  "dependencies": {
15
35
  "@modelcontextprotocol/sdk": "^1.29.0",
16
36
  "zod": "^3.24.1"
package/server.mjs CHANGED
@@ -2,9 +2,11 @@
2
2
  /**
3
3
  * ai-supply MCP server.
4
4
  *
5
- * Exposes the marketplace Agent API as MCP tools so any MCP-speaking agent
6
- * (Claude, etc.) can discover, install, purchase, download, publish, update and
7
- * review capabilities — everything a human can do.
5
+ * Exposes the ai-supply Agent API as MCP tools so any MCP-speaking agent
6
+ * (Claude, etc.) can discover, install, download, publish, update and review
7
+ * capabilities from a free, security-vetted registry — everything a human can do.
8
+ * Every listing is security-scanned and graded (0–100 score, A–D grade); risky
9
+ * (quarantined) ones are hidden by default and each result carries its score.
8
10
  *
9
11
  * Auth: set AIM_API_KEY (create one at /dashboard/api-keys). The server mints a
10
12
  * short-lived agent SESSION from your key on startup and uses it for calls, so
@@ -72,7 +74,7 @@ function result(r) {
72
74
  };
73
75
  }
74
76
 
75
- const server = new McpServer({ name: "ai-supply", version: "1.0.1" });
77
+ const server = new McpServer({ name: "ai-supply", version: "1.1.0" });
76
78
 
77
79
  const reg = (name, description, shape, handler) =>
78
80
  server.registerTool(name, { description, inputSchema: shape }, handler);
@@ -84,34 +86,30 @@ reg("whoami", "Identity, scopes and agreements of the authenticated agent.", {},
84
86
  reg("list_categories", "List categories and subcategories.", {}, async () =>
85
87
  result(await call("GET", "/api/v1/categories")),
86
88
  );
87
- reg("list_kinds", "List capability types (kinds) and pricing models.", {}, async () =>
89
+ reg("list_kinds", "List capability types (kinds).", {}, async () =>
88
90
  result(await call("GET", "/api/v1/kinds")),
89
91
  );
90
92
  reg(
91
93
  "search_listings",
92
- "Search the catalog. Filters: q, category, subcategory, kind, price(free|paid), sort(popular|rating|new), limit.",
94
+ "Search the security-vetted catalog. Filters: q, category, subcategory, kind, sort(popular|rating|new|security), limit. Every result carries a security score (0–100) + grade (A–D); risky (quarantined) listings are hidden by default. All listings are free.",
93
95
  {
94
96
  q: z.string().optional(),
95
97
  category: z.string().optional(),
96
98
  subcategory: z.string().optional(),
97
99
  kind: z.string().optional(),
98
- price: z.enum(["free", "paid"]).optional(),
99
- sort: z.enum(["popular", "rating", "new"]).optional(),
100
+ sort: z.enum(["popular", "rating", "new", "security"]).optional(),
100
101
  limit: z.number().int().min(1).max(100).optional(),
101
102
  },
102
103
  async (a) => result(await call("GET", "/api/v1/listings" + qs(a))),
103
104
  );
104
- reg("get_listing", "Get a listing's detail by slug.", { slug: z.string() }, async ({ slug }) =>
105
+ reg("get_listing", "Get a listing's full detail by slug — including its security score, grade, level and scan findings.", { slug: z.string() }, async ({ slug }) =>
105
106
  result(await call("GET", `/api/v1/listings/${slug}`)),
106
107
  );
107
108
 
108
109
  // ---- Consume ----
109
- reg("install_listing", "Install a free listing (records ownership).", { slug: z.string() }, async ({ slug }) =>
110
+ reg("install_listing", "Install a listing (free; records ownership). Downloads are gated on a passing security scan.", { slug: z.string() }, async ({ slug }) =>
110
111
  result(await call("POST", `/api/v1/listings/${slug}/install`)),
111
112
  );
112
- reg("purchase_listing", "Purchase a paid listing (needs 'purchase' scope; respects spend cap).", { slug: z.string() }, async ({ slug }) =>
113
- result(await call("POST", `/api/v1/listings/${slug}/purchase`)),
114
- );
115
113
  reg("download_listing", "Fetch the latest version artifact ref for an owned listing.", { slug: z.string() }, async ({ slug }) =>
116
114
  result(await call("GET", `/api/v1/listings/${slug}/download`)),
117
115
  );
@@ -139,8 +137,6 @@ reg(
139
137
  subcategorySlug: z.string().optional(),
140
138
  shortDesc: z.string(),
141
139
  longDescriptionMd: z.string().optional(),
142
- pricingModel: z.enum(["FREE", "ONE_TIME", "PER_CALL", "SUBSCRIPTION"]).optional(),
143
- priceAmount: z.number().int().optional(),
144
140
  version: z.string().optional(),
145
141
  versionContent: z.string().optional(),
146
142
  filePath: z.string().optional(),
@@ -157,8 +153,6 @@ reg(
157
153
  name: z.string().optional(),
158
154
  shortDesc: z.string().optional(),
159
155
  longDescriptionMd: z.string().optional(),
160
- pricingModel: z.enum(["FREE", "ONE_TIME", "PER_CALL", "SUBSCRIPTION"]).optional(),
161
- priceAmount: z.number().int().optional(),
162
156
  status: z.enum(["DRAFT", "PUBLISHED", "SUSPENDED"]).optional(),
163
157
  },
164
158
  async ({ slug, ...patch }) => result(await call("PATCH", `/api/v1/listings/${slug}`, patch)),
@@ -194,9 +188,6 @@ reg(
194
188
  { kind: z.enum(["terms", "publisher", "both"]).optional() },
195
189
  async (a) => result(await call("POST", "/api/v1/me/accept", a)),
196
190
  );
197
- reg("my_revenue", "Aggregate (mock) revenue for your listings.", {}, async () =>
198
- result(await call("GET", "/api/v1/me/revenue")),
199
- );
200
191
 
201
192
  if (API_KEY) await mintSession();
202
193
  await server.connect(new StdioServerTransport());