chekk-mcp 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.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Chekk MCP Server
4
+ *
5
+ * Makes every project deployed on chekk.dev available as agent-callable
6
+ * tools via the Model Context Protocol.
7
+ *
8
+ * Usage (Claude Desktop / Cursor / any MCP client):
9
+ * npx @chekk/mcp-server
10
+ *
11
+ * Tools exposed:
12
+ * - chekk_search_tools Search Chekk's project index by keyword, framework, etc.
13
+ * - chekk_get_manifest Get the full agent manifest for a specific project.
14
+ * - chekk_call Call an action on a Chekk-deployed project (proxied).
15
+ */
16
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,361 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Chekk MCP Server
4
+ *
5
+ * Makes every project deployed on chekk.dev available as agent-callable
6
+ * tools via the Model Context Protocol.
7
+ *
8
+ * Usage (Claude Desktop / Cursor / any MCP client):
9
+ * npx @chekk/mcp-server
10
+ *
11
+ * Tools exposed:
12
+ * - chekk_search_tools Search Chekk's project index by keyword, framework, etc.
13
+ * - chekk_get_manifest Get the full agent manifest for a specific project.
14
+ * - chekk_call Call an action on a Chekk-deployed project (proxied).
15
+ */
16
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
17
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
+ import { z } from "zod";
19
+ const CHEKK_API = process.env.CHEKK_API_URL || "https://chekk.dev/api/v1";
20
+ // ---------------------------------------------------------------------------
21
+ // Helpers
22
+ // ---------------------------------------------------------------------------
23
+ async function chekkFetch(path, init) {
24
+ const url = path.startsWith("http") ? path : `${CHEKK_API}${path}`;
25
+ const res = await fetch(url, {
26
+ ...init,
27
+ headers: {
28
+ "User-Agent": "chekk-mcp-server/0.1.0",
29
+ "Accept": "application/json",
30
+ ...(init?.headers || {}),
31
+ },
32
+ });
33
+ return res;
34
+ }
35
+ // ---------------------------------------------------------------------------
36
+ // Server
37
+ // ---------------------------------------------------------------------------
38
+ const server = new McpServer({
39
+ name: "chekk",
40
+ version: "0.1.0",
41
+ });
42
+ // ---------------------------------------------------------------------------
43
+ // Tool 1: chekk_search_tools
44
+ // ---------------------------------------------------------------------------
45
+ server.registerTool("chekk_search_tools", {
46
+ title: "Search Chekk Tools",
47
+ description: "Search Chekk's index of deployed projects that agents can call. " +
48
+ "Returns projects with their available actions, payment requirements, " +
49
+ "and entry points. Use this to discover what tools are available on Chekk.",
50
+ inputSchema: {
51
+ query: z
52
+ .string()
53
+ .optional()
54
+ .describe("Keyword search across project names and descriptions"),
55
+ framework: z
56
+ .string()
57
+ .optional()
58
+ .describe("Filter by framework: nextjs, react, fastapi, express, flask, django, etc."),
59
+ has_payment: z
60
+ .boolean()
61
+ .optional()
62
+ .describe("Filter to projects that accept USDC payments"),
63
+ has_auth: z
64
+ .boolean()
65
+ .optional()
66
+ .describe("Filter to projects that require authentication"),
67
+ min_actions: z
68
+ .number()
69
+ .int()
70
+ .min(0)
71
+ .optional()
72
+ .describe("Minimum number of callable actions"),
73
+ limit: z
74
+ .number()
75
+ .int()
76
+ .min(1)
77
+ .max(50)
78
+ .optional()
79
+ .describe("Max results to return (default 20)"),
80
+ },
81
+ }, async (args) => {
82
+ const params = new URLSearchParams();
83
+ if (args.query)
84
+ params.set("q", args.query);
85
+ if (args.framework)
86
+ params.set("framework", args.framework);
87
+ if (args.has_payment !== undefined)
88
+ params.set("has_payment", String(args.has_payment));
89
+ if (args.has_auth !== undefined)
90
+ params.set("has_auth", String(args.has_auth));
91
+ if (args.min_actions !== undefined)
92
+ params.set("min_actions", String(args.min_actions));
93
+ params.set("limit", String(args.limit || 20));
94
+ const res = await chekkFetch(`/agents/search?${params}`);
95
+ if (!res.ok) {
96
+ return {
97
+ content: [
98
+ {
99
+ type: "text",
100
+ text: `Error searching Chekk: HTTP ${res.status} — ${await res.text()}`,
101
+ },
102
+ ],
103
+ isError: true,
104
+ };
105
+ }
106
+ const data = await res.json();
107
+ const items = (data.items || []).map((item) => ({
108
+ project: item.slug,
109
+ title: item.title || item.repo,
110
+ description: item.description,
111
+ framework: item.framework,
112
+ actions_count: item.actions_count,
113
+ requires_auth: item.requires?.auth || false,
114
+ requires_payment: item.requires?.payment || false,
115
+ manifest_url: item.well_known,
116
+ chat_url: item.chat,
117
+ }));
118
+ return {
119
+ content: [
120
+ {
121
+ type: "text",
122
+ text: JSON.stringify({
123
+ total: data.count,
124
+ results: items,
125
+ hint: "Use chekk_get_manifest with a project slug to see all available actions, " +
126
+ "or chekk_call to invoke an action directly.",
127
+ }, null, 2),
128
+ },
129
+ ],
130
+ };
131
+ });
132
+ // ---------------------------------------------------------------------------
133
+ // Tool 2: chekk_get_manifest
134
+ // ---------------------------------------------------------------------------
135
+ server.registerTool("chekk_get_manifest", {
136
+ title: "Get Project Manifest",
137
+ description: "Get the full agent manifest for a Chekk-deployed project. " +
138
+ "Returns all callable actions with their HTTP methods, paths, " +
139
+ "required inputs, payment prices, and auth requirements. " +
140
+ "Use this to understand what a specific project can do before calling it.",
141
+ inputSchema: {
142
+ project: z
143
+ .string()
144
+ .describe('Project slug in "owner/repo" format, e.g. "greatdaveo/DavShop-Api"'),
145
+ },
146
+ }, async (args) => {
147
+ const [owner, repo] = args.project.split("/");
148
+ if (!owner || !repo) {
149
+ return {
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: 'Invalid project slug. Use "owner/repo" format.',
154
+ },
155
+ ],
156
+ isError: true,
157
+ };
158
+ }
159
+ const res = await chekkFetch(`/agent/${owner}/${repo}/manifest`);
160
+ if (!res.ok) {
161
+ if (res.status === 404) {
162
+ return {
163
+ content: [
164
+ {
165
+ type: "text",
166
+ text: `Project "${args.project}" not found or has no agent manifest. ` +
167
+ `Try chekk_search_tools to find available projects.`,
168
+ },
169
+ ],
170
+ isError: true,
171
+ };
172
+ }
173
+ return {
174
+ content: [
175
+ {
176
+ type: "text",
177
+ text: `Error fetching manifest: HTTP ${res.status}`,
178
+ },
179
+ ],
180
+ isError: true,
181
+ };
182
+ }
183
+ const manifest = await res.json();
184
+ // Summarize for the agent
185
+ const actions = (manifest.actions || []).map((a) => ({
186
+ id: a.id,
187
+ method: a.method,
188
+ path: a.path,
189
+ description: a.description,
190
+ side_effect: a.side_effect,
191
+ inputs: a.inputs,
192
+ }));
193
+ const summary = {
194
+ project: manifest.slug,
195
+ description: manifest.description,
196
+ framework: manifest.framework,
197
+ deployed_url: manifest.deployed_url,
198
+ actions_count: actions.length,
199
+ actions,
200
+ requires_auth: manifest.requires?.auth || false,
201
+ requires_payment: manifest.requires?.payment || false,
202
+ payment_info: manifest.payment || null,
203
+ session: manifest.session || null,
204
+ hint: "Use chekk_call with the project slug, method, path, and body to invoke an action.",
205
+ };
206
+ return {
207
+ content: [
208
+ {
209
+ type: "text",
210
+ text: JSON.stringify(summary, null, 2),
211
+ },
212
+ ],
213
+ };
214
+ });
215
+ // ---------------------------------------------------------------------------
216
+ // Tool 3: chekk_call
217
+ // ---------------------------------------------------------------------------
218
+ server.registerTool("chekk_call", {
219
+ title: "Call a Chekk Tool",
220
+ description: "Execute an action on a Chekk-deployed project. " +
221
+ "Proxies your request through Chekk's agent gateway, which handles " +
222
+ "rate limiting, payment enforcement (402 challenges), and routing. " +
223
+ "If the action requires payment, you'll receive a 402 response with " +
224
+ "instructions to pay USDC on Base.",
225
+ inputSchema: {
226
+ project: z
227
+ .string()
228
+ .describe('Project slug in "owner/repo" format, e.g. "greatdaveo/DavShop-Api"'),
229
+ method: z
230
+ .enum(["GET", "POST", "PUT", "PATCH", "DELETE"])
231
+ .default("POST")
232
+ .describe("HTTP method for the action"),
233
+ path: z
234
+ .string()
235
+ .describe('API path to call, e.g. "/api/orders"'),
236
+ body: z
237
+ .record(z.unknown())
238
+ .optional()
239
+ .describe("Request body (JSON object) for POST/PUT/PATCH"),
240
+ query: z
241
+ .record(z.string())
242
+ .optional()
243
+ .describe("Query parameters as key-value pairs"),
244
+ payment_receipt: z
245
+ .string()
246
+ .optional()
247
+ .describe("Payment receipt ID from a previous 402 challenge (after paying USDC)"),
248
+ },
249
+ }, async (args) => {
250
+ const [owner, repo] = args.project.split("/");
251
+ if (!owner || !repo) {
252
+ return {
253
+ content: [
254
+ {
255
+ type: "text",
256
+ text: 'Invalid project slug. Use "owner/repo" format.',
257
+ },
258
+ ],
259
+ isError: true,
260
+ };
261
+ }
262
+ const headers = {
263
+ "Content-Type": "application/json",
264
+ };
265
+ if (args.payment_receipt) {
266
+ headers["X-Payment-Receipt"] = args.payment_receipt;
267
+ }
268
+ const callBody = {
269
+ method: args.method,
270
+ path: args.path,
271
+ };
272
+ if (args.body)
273
+ callBody.body = args.body;
274
+ if (args.query)
275
+ callBody.query = args.query;
276
+ const res = await chekkFetch(`/agent/${owner}/${repo}/call`, {
277
+ method: "POST",
278
+ headers,
279
+ body: JSON.stringify(callBody),
280
+ });
281
+ const data = await res.json();
282
+ if (res.status === 402) {
283
+ // Payment required — return the challenge
284
+ return {
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: JSON.stringify({
289
+ status: "payment_required",
290
+ message: data.message,
291
+ receipt_id: data.receipt_id,
292
+ challenge: data.challenge,
293
+ hint: data.hint,
294
+ next_step: "Pay the USDC amount to the specified address on Base, " +
295
+ "then call chekk_call again with payment_receipt set to the receipt_id.",
296
+ }, null, 2),
297
+ },
298
+ ],
299
+ };
300
+ }
301
+ if (res.status === 429) {
302
+ return {
303
+ content: [
304
+ {
305
+ type: "text",
306
+ text: JSON.stringify({
307
+ status: "rate_limited",
308
+ message: data.message,
309
+ retry_after_seconds: data.retry_after_seconds,
310
+ scope: data.scope,
311
+ }, null, 2),
312
+ },
313
+ ],
314
+ isError: true,
315
+ };
316
+ }
317
+ if (!res.ok) {
318
+ return {
319
+ content: [
320
+ {
321
+ type: "text",
322
+ text: JSON.stringify({
323
+ status: "error",
324
+ http_status: res.status,
325
+ error: data,
326
+ }, null, 2),
327
+ },
328
+ ],
329
+ isError: true,
330
+ };
331
+ }
332
+ // Success
333
+ return {
334
+ content: [
335
+ {
336
+ type: "text",
337
+ text: JSON.stringify({
338
+ status: "success",
339
+ upstream_status: data.upstream_status,
340
+ result: data.upstream_body,
341
+ paid: data.paid || false,
342
+ receipt_id: data.receipt_id || null,
343
+ response_time_ms: data.upstream_seconds
344
+ ? Math.round(data.upstream_seconds * 1000)
345
+ : null,
346
+ }, null, 2),
347
+ },
348
+ ],
349
+ };
350
+ });
351
+ // ---------------------------------------------------------------------------
352
+ // Start
353
+ // ---------------------------------------------------------------------------
354
+ async function main() {
355
+ const transport = new StdioServerTransport();
356
+ await server.connect(transport);
357
+ }
358
+ main().catch((err) => {
359
+ console.error("Chekk MCP server failed to start:", err);
360
+ process.exit(1);
361
+ });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "chekk-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server that exposes every Chekk-deployed project as agent-callable tools",
5
+ "type": "module",
6
+ "bin": {
7
+ "chekk-mcp": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts"
14
+ },
15
+ "files": ["dist"],
16
+ "keywords": ["mcp", "chekk", "agent", "tools", "llm"],
17
+ "license": "MIT",
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.12.0",
20
+ "zod": "^3.24.0"
21
+ },
22
+ "devDependencies": {
23
+ "typescript": "^5.7.0",
24
+ "tsx": "^4.19.0",
25
+ "@types/node": "^22.0.0"
26
+ }
27
+ }