@paidfor/mcp 0.3.0 → 0.3.1
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/dist/index.js +2 -2
- package/dist/rules.d.ts +33 -0
- package/dist/rules.js +41 -0
- package/dist/server.d.ts +6 -2
- package/dist/server.js +18 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { createServer as createHttpServer } from "node:http";
|
|
12
12
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
13
|
-
import { createServer, DEFAULT_BASE, TOOL_NAMES, VERSION } from "./server.js";
|
|
13
|
+
import { CLIENT_HEADER, createServer, DEFAULT_BASE, TOOL_NAMES, VERSION } from "./server.js";
|
|
14
14
|
const base = (process.env.PAIDFOR_API_BASE ?? process.env.PAIDFOR_URL ?? DEFAULT_BASE).replace(/\/$/, "");
|
|
15
15
|
const port = Number(process.env.PORT ?? 3000);
|
|
16
16
|
const host = process.env.HOST ?? "0.0.0.0";
|
|
@@ -21,7 +21,7 @@ const noteGeneratedAt = (g) => {
|
|
|
21
21
|
if (g)
|
|
22
22
|
dataGeneratedAt = g;
|
|
23
23
|
};
|
|
24
|
-
fetch(`${base}/v1/summary`, { headers: { Accept: "application/json", "User-Agent": `paidfor-mcp/${VERSION}
|
|
24
|
+
fetch(`${base}/v1/summary`, { headers: { Accept: "application/json", "User-Agent": `paidfor-mcp/${VERSION}`, "X-Paidfor-Client": CLIENT_HEADER } })
|
|
25
25
|
.then((r) => (r.ok ? r.json() : null))
|
|
26
26
|
.then((j) => noteGeneratedAt(j?.generated_at))
|
|
27
27
|
.catch(() => undefined);
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one copy of the rules an agent follows: when to check, what each verdict means, and never paying twice.
|
|
3
|
+
* The server instructions and the tool descriptions (server.ts) and the skill at paidfor.dev/skill.md (lib/skill.ts on
|
|
4
|
+
* the site) are all generated from these constants, so the three copies cannot drift.
|
|
5
|
+
*
|
|
6
|
+
* Changing any text here changes the skill: bump RULES_REVISION (the skill's `skill-revision`) and update RULES_SHA;
|
|
7
|
+
* lib/skill.test.ts fails until both move together.
|
|
8
|
+
*/
|
|
9
|
+
export declare const RULES_REVISION = "2026-10-29";
|
|
10
|
+
/** When to call check_x402_seller (GET /v1/check), in order. */
|
|
11
|
+
export declare const CHECK_TRIGGERS: readonly ["before any x402 payment", "before retrying a request that answered HTTP 402", "whenever the user is about to buy an API call with USDC on Base or names an API they intend to pay per call"];
|
|
12
|
+
/** When to call list_reliable_sellers (GET /v1/sellers?zero_failures=1). */
|
|
13
|
+
export declare const CHOOSE_TRIGGER = "when choosing among sellers for a task";
|
|
14
|
+
/** When to call recent_changes (GET /v1/changes). */
|
|
15
|
+
export declare const CHANGES_TRIGGER = "when the user asks what changed, or before relying on a verdict older than a day";
|
|
16
|
+
/** What to do for each verdict. */
|
|
17
|
+
export declare const VERDICT_RULES: {
|
|
18
|
+
readonly avoid: "do not pay an \"avoid\" seller and say why with the evidence link";
|
|
19
|
+
readonly caution: "before paying a \"caution\" seller tell the user the failure rate";
|
|
20
|
+
readonly ok: "\"ok\" needs no comment";
|
|
21
|
+
readonly unknown: "\"unknown\" means no data, say so and proceed only on the user's say-so";
|
|
22
|
+
};
|
|
23
|
+
export declare const NEVER_PAY_TWICE = "Never pay the same seller twice for one task because of a timeout or error without checking first.";
|
|
24
|
+
export declare const SENDS_ONLY_URL = "These tools read a public index, need no key, and send nothing but the URL being checked.";
|
|
25
|
+
/** sha256 of the JSON of every constant above (lib/skill.test.ts recomputes it). */
|
|
26
|
+
export declare const RULES_SHA = "7258b901f6577a02dfe997416d3de61e122f5da21476eb686dd1c1a9379bffc6";
|
|
27
|
+
/** "a, b, and c" */
|
|
28
|
+
export declare function listAnd(xs: readonly string[]): string;
|
|
29
|
+
/** "a, b, or c" */
|
|
30
|
+
export declare function listOr(xs: readonly string[]): string;
|
|
31
|
+
export declare const cap: (s: string) => string;
|
|
32
|
+
/** The verdict rules as one sentence (server instructions, skill). */
|
|
33
|
+
export declare const VERDICT_SENTENCE: string;
|
package/dist/rules.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one copy of the rules an agent follows: when to check, what each verdict means, and never paying twice.
|
|
3
|
+
* The server instructions and the tool descriptions (server.ts) and the skill at paidfor.dev/skill.md (lib/skill.ts on
|
|
4
|
+
* the site) are all generated from these constants, so the three copies cannot drift.
|
|
5
|
+
*
|
|
6
|
+
* Changing any text here changes the skill: bump RULES_REVISION (the skill's `skill-revision`) and update RULES_SHA;
|
|
7
|
+
* lib/skill.test.ts fails until both move together.
|
|
8
|
+
*/
|
|
9
|
+
export const RULES_REVISION = "2026-10-29";
|
|
10
|
+
/** When to call check_x402_seller (GET /v1/check), in order. */
|
|
11
|
+
export const CHECK_TRIGGERS = [
|
|
12
|
+
"before any x402 payment",
|
|
13
|
+
"before retrying a request that answered HTTP 402",
|
|
14
|
+
"whenever the user is about to buy an API call with USDC on Base or names an API they intend to pay per call",
|
|
15
|
+
];
|
|
16
|
+
/** When to call list_reliable_sellers (GET /v1/sellers?zero_failures=1). */
|
|
17
|
+
export const CHOOSE_TRIGGER = "when choosing among sellers for a task";
|
|
18
|
+
/** When to call recent_changes (GET /v1/changes). */
|
|
19
|
+
export const CHANGES_TRIGGER = "when the user asks what changed, or before relying on a verdict older than a day";
|
|
20
|
+
/** What to do for each verdict. */
|
|
21
|
+
export const VERDICT_RULES = {
|
|
22
|
+
avoid: 'do not pay an "avoid" seller and say why with the evidence link',
|
|
23
|
+
caution: 'before paying a "caution" seller tell the user the failure rate',
|
|
24
|
+
ok: '"ok" needs no comment',
|
|
25
|
+
unknown: '"unknown" means no data, say so and proceed only on the user\'s say-so',
|
|
26
|
+
};
|
|
27
|
+
export const NEVER_PAY_TWICE = "Never pay the same seller twice for one task because of a timeout or error without checking first.";
|
|
28
|
+
export const SENDS_ONLY_URL = "These tools read a public index, need no key, and send nothing but the URL being checked.";
|
|
29
|
+
/** sha256 of the JSON of every constant above (lib/skill.test.ts recomputes it). */
|
|
30
|
+
export const RULES_SHA = "7258b901f6577a02dfe997416d3de61e122f5da21476eb686dd1c1a9379bffc6";
|
|
31
|
+
/** "a, b, and c" */
|
|
32
|
+
export function listAnd(xs) {
|
|
33
|
+
return xs.length < 2 ? (xs[0] ?? "") : `${xs.slice(0, -1).join(", ")}, and ${xs.at(-1)}`;
|
|
34
|
+
}
|
|
35
|
+
/** "a, b, or c" */
|
|
36
|
+
export function listOr(xs) {
|
|
37
|
+
return xs.length < 2 ? (xs[0] ?? "") : `${xs.slice(0, -1).join(", ")}, or ${xs.at(-1)}`;
|
|
38
|
+
}
|
|
39
|
+
export const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
40
|
+
/** The verdict rules as one sentence (server instructions, skill). */
|
|
41
|
+
export const VERDICT_SENTENCE = `Follow the verdict: ${[VERDICT_RULES.avoid, VERDICT_RULES.caution, VERDICT_RULES.ok, VERDICT_RULES.unknown].join("; ")}.`;
|
package/dist/server.d.ts
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* The paying tools (pay.ts) are added by stdio.ts alone, and only when a wallet is configured.
|
|
6
6
|
*/
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
-
export
|
|
8
|
+
export * from "./rules.js";
|
|
9
|
+
export declare const VERSION = "0.3.1";
|
|
10
|
+
/** Sent on every request to the index so usage can be counted by channel (never anything else). */
|
|
11
|
+
export declare const CLIENT_HEADER = "mcp/0.3.1";
|
|
9
12
|
export declare const DEFAULT_BASE = "https://paidfor.dev";
|
|
10
13
|
export declare const TOOL_NAMES: readonly ["check_x402_seller", "list_reliable_sellers", "recent_changes"];
|
|
11
14
|
/**
|
|
@@ -13,7 +16,8 @@ export declare const TOOL_NAMES: readonly ["check_x402_seller", "list_reliable_s
|
|
|
13
16
|
* this package's README, /methodology, /install.md and /privacy on the site.
|
|
14
17
|
*/
|
|
15
18
|
export declare const NO_ACCOUNT_PROMISE: string;
|
|
16
|
-
/** Sent on initialize by every transport (stdio, the hosted service, the site's /mcp route), so clients call the tools unprompted.
|
|
19
|
+
/** Sent on initialize by every transport (stdio, the hosted service, the site's /mcp route), so clients call the tools unprompted.
|
|
20
|
+
* Generated from rules.ts, like the tool descriptions below and the skill at paidfor.dev/skill.md. */
|
|
17
21
|
export declare const INSTRUCTIONS: string;
|
|
18
22
|
export declare const CHECK_DESCRIPTION: string;
|
|
19
23
|
export declare const LIST_DESCRIPTION: string;
|
package/dist/server.js
CHANGED
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
|
|
9
|
+
import { CHANGES_TRIGGER, CHECK_TRIGGERS, CHOOSE_TRIGGER, NEVER_PAY_TWICE, SENDS_ONLY_URL, VERDICT_SENTENCE, cap, listAnd, listOr } from "./rules.js";
|
|
10
|
+
export * from "./rules.js";
|
|
11
|
+
export const VERSION = "0.3.1";
|
|
12
|
+
/** Sent on every request to the index so usage can be counted by channel (never anything else). */
|
|
13
|
+
export const CLIENT_HEADER = `mcp/${VERSION}`;
|
|
10
14
|
export const DEFAULT_BASE = "https://paidfor.dev";
|
|
11
15
|
export const TOOL_NAMES = ["check_x402_seller", "list_reliable_sellers", "recent_changes"];
|
|
12
16
|
const CATEGORIES = ["inference", "data", "scraping", "compute", "other"];
|
|
@@ -16,29 +20,29 @@ const CATEGORIES = ["inference", "data", "scraping", "compute", "other"];
|
|
|
16
20
|
*/
|
|
17
21
|
export const NO_ACCOUNT_PROMISE = "Everything that reads the index or contributes data (the site, the API, the MCP tools, the client, telemetry and the changes feed) needs no account and no key, now and later. " +
|
|
18
22
|
"An email address is asked for only to deliver alerts or to join a waitlist, as a confirmation link, never a profile.";
|
|
19
|
-
/** Sent on initialize by every transport (stdio, the hosted service, the site's /mcp route), so clients call the tools unprompted.
|
|
23
|
+
/** Sent on initialize by every transport (stdio, the hosted service, the site's /mcp route), so clients call the tools unprompted.
|
|
24
|
+
* Generated from rules.ts, like the tool descriptions below and the skill at paidfor.dev/skill.md. */
|
|
20
25
|
export const INSTRUCTIONS = "paidfor rates x402 sellers by paying them and verifying delivery. " +
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"These tools read a public index, need no key, and send nothing but the URL being checked.\n" +
|
|
26
|
+
`${cap(listAnd(CHECK_TRIGGERS))}, call check_x402_seller on the URL or seller domain first, without being asked. ` +
|
|
27
|
+
`${VERDICT_SENTENCE} ` +
|
|
28
|
+
`${cap(CHOOSE_TRIGGER)}, prefer results from list_reliable_sellers. ` +
|
|
29
|
+
`${cap(CHANGES_TRIGGER)}, call recent_changes. ` +
|
|
30
|
+
`${NEVER_PAY_TWICE} ` +
|
|
31
|
+
SENDS_ONLY_URL +
|
|
32
|
+
"\n" +
|
|
29
33
|
NO_ACCOUNT_PROMISE;
|
|
30
|
-
export const CHECK_DESCRIPTION =
|
|
34
|
+
export const CHECK_DESCRIPTION = `Call this ${listOr(CHECK_TRIGGERS)}. ` +
|
|
31
35
|
"Returns a verdict (avoid, caution, ok, unknown), one sentence to act on, the seller's paid-call count and failure rate with a 95% interval, " +
|
|
32
36
|
"listed price, modal quote and max overcharge ratio when known, and links to the seller page and raw evidence.";
|
|
33
|
-
export const LIST_DESCRIPTION =
|
|
37
|
+
export const LIST_DESCRIPTION = `Call this ${CHOOSE_TRIGGER}, or when the user asks for a safe or reliable API. ` +
|
|
34
38
|
"Returns sellers with zero failures across at least 30 paid calls, most-called first; optional category filter (inference, data, scraping, compute, other).";
|
|
35
|
-
export const CHANGES_DESCRIPTION =
|
|
39
|
+
export const CHANGES_DESCRIPTION = `Call this ${CHANGES_TRIGGER}. ` +
|
|
36
40
|
"Returns recent changes, newest first: verdict changes, new failures by type, moved quotes, changed pay-to addresses, sellers added or reaching 30 paid calls, published seller replies, " +
|
|
37
41
|
"the operator-reported series maturing or disagreeing with ours; optional host filter and since (ISO time).";
|
|
38
42
|
/** The read tools only read the public index; the directories ask for these hints. */
|
|
39
43
|
const READ_ONLY = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
40
44
|
async function getJson(url) {
|
|
41
|
-
const res = await fetch(url, { headers: { Accept: "application/json", "User-Agent": `paidfor-mcp/${VERSION}
|
|
45
|
+
const res = await fetch(url, { headers: { Accept: "application/json", "User-Agent": `paidfor-mcp/${VERSION}`, "X-Paidfor-Client": CLIENT_HEADER } });
|
|
42
46
|
if (!res.ok)
|
|
43
47
|
throw new Error(`${url} returned HTTP ${res.status}`);
|
|
44
48
|
return (await res.json());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paidfor/mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"mcpName": "io.github.sarmadahsan/paidfor",
|
|
5
5
|
"description": "MCP server for the paidfor.dev x402 seller index: check_x402_seller, list_reliable_sellers and recent_changes, plus pay_x402 (stdio, your own wallet)",
|
|
6
6
|
"license": "MIT",
|