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.
- package/README.md +5 -5
- package/package.json +26 -6
- 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-
|
|
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`, `
|
|
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 (
|
|
35
|
+
## Tools (17)
|
|
36
36
|
|
|
37
|
-
`whoami`, `list_categories`, `list_kinds`, `search_listings`, `get_listing`, `install_listing`, `
|
|
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
|
|
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
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"bin": {
|
|
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": {
|
|
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": [
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
6
|
-
* (Claude, etc.) can discover, install,
|
|
7
|
-
*
|
|
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
|
|
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)
|
|
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,
|
|
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
|
-
|
|
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
|
|
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());
|