@agentutility/mcp-statline 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.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # @agentutility/mcp-statline
2
+
3
+ > Sports and stats math, per call.
4
+
5
+ Live win probability and the analytics around a game — model the rest of a match from the current score and time, no upstream feed required.
6
+
7
+ **Pricing:** pay-per-call in USDC on Base. No subscriptions, no API keys. See per-tool prices below.
8
+
9
+ ## Install — Claude Desktop
10
+
11
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
12
+
13
+ ```json
14
+ {
15
+ "mcpServers": {
16
+ "agentutility-statline": {
17
+ "command": "npx",
18
+ "args": ["-y", "@agentutility/mcp-statline"],
19
+ "env": { "X402_PRIVATE_KEY": "0xYOUR_PRIVATE_KEY_HEX" }
20
+ }
21
+ }
22
+ }
23
+ ```
24
+
25
+ Restart Claude Desktop. 1 tools appear in the tool palette.
26
+
27
+ ## Install — Cursor
28
+
29
+ Add to `.cursor/mcp.json`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "agentutility-statline": {
35
+ "command": "npx",
36
+ "args": ["-y", "@agentutility/mcp-statline"],
37
+ "env": { "X402_PRIVATE_KEY": "0x..." }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## Funding
44
+
45
+ Send any amount of **USDC on Base mainnet** to the address derived from your `X402_PRIVATE_KEY`. The MCP server uses it to pay for tool calls automatically.
46
+
47
+ USDC on Base contract: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`
48
+
49
+ ## Tools (1)
50
+
51
+ | Tool | Description |
52
+ |---|---|
53
+ | `win-prob` | (0.003 USDC/call) Live sports win probability API / in-game win probability calculator / NFL NBA MLB NHL soccer win chance from current score and time remaining. Models the rest of the game as a random walk on the score margin (final margin = current margin + a normal increment whose mean is the pregame edge accrued over the time left and whose std dev is the sport's final-margin volatility scaled by sqrt of time remaining), then returns each team's win probability as the normal CDF of the projected final margin, plus projected final margin, the 1-sigma swing still possible, and human-readable drivers. Pure deterministic compute, no upstream API. Built-in scoring volatility for NFL/NCAAF/NBA/NCAAB/WNBA/MLB/NHL/soccer; override scoring_std for any sport. Statistical estimate, not betting advice. |
54
+
55
+ ## How it works
56
+
57
+ 1. Agent calls a tool (e.g. `win-prob`).
58
+ 2. MCP server POSTs to `https://x402.agentutility.ai/win-prob`.
59
+ 3. The endpoint responds **HTTP 402** with payment instructions.
60
+ 4. The MCP server signs an EIP-3009 USDC transfer authorization with `X402_PRIVATE_KEY` and retries.
61
+ 5. CDP facilitator settles on Base.
62
+ 6. The endpoint returns the actual response.
63
+
64
+ The agent never sees the payment flow — it just gets the result.
65
+
66
+ ## Links
67
+
68
+ - Cluster overview: https://agentutility.ai/statline/
69
+ - All MCP packages: https://mcp.agentutility.ai/
70
+ - Source: https://github.com/rooz21/x402/tree/main/packages/mcp-statline
71
+
72
+ ---
73
+
74
+ **Version:** 0.1.0 · **License:** MIT
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @agentutility/mcp-<cluster> — stdio MCP server exposing the cluster's
4
+ * x402-paid endpoints as MCP tools. Forwards every CallToolRequest to
5
+ * x402.agentutility.ai, where @x402/fetch handles 402 → payment → retry
6
+ * using the agent's own wallet (X402_PRIVATE_KEY env var).
7
+ *
8
+ * Boilerplate is single-sourced at packages/_template/src/index.ts and
9
+ * copied verbatim into each packages/mcp-<cluster>/src/index.ts by
10
+ * scripts/generate-mcp-clusters.mjs. The codegen also writes a matching
11
+ * tools.generated.ts so this file imports CLUSTER_SLUG + VERSION + TOOLS
12
+ * rather than hard-coding.
13
+ *
14
+ * Required env: X402_PRIVATE_KEY (hex EVM key, USDC on Base).
15
+ * Optional env: X402_BASE_URL (default https://x402.agentutility.ai)
16
+ * X402_RPC_URL (default https://mainnet.base.org)
17
+ */
18
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
19
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
20
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
21
+ import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
22
+ import { ExactEvmScheme, toClientEvmSigner } from "@x402/evm";
23
+ import { privateKeyToAccount } from "viem/accounts";
24
+ import { createPublicClient, http } from "viem";
25
+ import { base } from "viem/chains";
26
+ import { TOOLS, CLUSTER_SLUG, VERSION } from "./tools.generated.js";
27
+ const BASE_URL = (process.env.X402_BASE_URL || "https://x402.agentutility.ai").replace(/\/$/, "");
28
+ const RPC_URL = process.env.X402_RPC_URL || "https://mainnet.base.org";
29
+ const PK = process.env.X402_PRIVATE_KEY;
30
+ if (!PK) {
31
+ console.error(`[@agentutility/mcp-${CLUSTER_SLUG}] FATAL: X402_PRIVATE_KEY env var is required.`);
32
+ console.error("Set it to a hex-encoded EVM private key with USDC balance on Base (chain 8453).");
33
+ console.error("USDC on Base: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913");
34
+ process.exit(1);
35
+ }
36
+ const account = privateKeyToAccount((PK.startsWith("0x") ? PK : `0x${PK}`));
37
+ const publicClient = createPublicClient({
38
+ chain: base,
39
+ transport: http(RPC_URL),
40
+ });
41
+ const signer = toClientEvmSigner(account, publicClient);
42
+ const client = new x402Client().register("eip155:8453", new ExactEvmScheme(signer));
43
+ const paidFetch = wrapFetchWithPayment(fetch, client);
44
+ async function trackedFetch(url, init) {
45
+ const headers = new Headers(init?.headers);
46
+ headers.set("X-Agent-Channel", `mcp-stdio-${CLUSTER_SLUG}`);
47
+ headers.set("X-Agent-Id", "47167");
48
+ if (!headers.has("User-Agent")) {
49
+ headers.set("User-Agent", `agentutility-mcp/${CLUSTER_SLUG}/${VERSION}`);
50
+ }
51
+ return paidFetch(url, { ...init, headers });
52
+ }
53
+ const server = new Server({ name: `agentutility-${CLUSTER_SLUG}`, version: VERSION }, { capabilities: { tools: {} } });
54
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
55
+ tools: TOOLS.map((t) => ({
56
+ name: t.name,
57
+ description: t.description,
58
+ inputSchema: t.input_schema,
59
+ })),
60
+ }));
61
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
62
+ const name = req.params.name;
63
+ const tool = TOOLS.find((t) => t.name === name);
64
+ if (!tool) {
65
+ return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
66
+ }
67
+ try {
68
+ const res = await trackedFetch(`${BASE_URL}/${tool.http_name}`, {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify(req.params.arguments ?? {}),
72
+ });
73
+ const body = await res.text();
74
+ if (!res.ok) {
75
+ return { content: [{ type: "text", text: `HTTP ${res.status}: ${body}` }], isError: true };
76
+ }
77
+ return { content: [{ type: "text", text: body }] };
78
+ }
79
+ catch (err) {
80
+ return {
81
+ content: [{ type: "text", text: `tool call failed: ${err instanceof Error ? err.message : String(err)}` }],
82
+ isError: true,
83
+ };
84
+ }
85
+ });
86
+ await server.connect(new StdioServerTransport());
@@ -0,0 +1,60 @@
1
+ /** Auto-generated by scripts/generate-mcp-clusters.mjs. Do not edit by hand. */
2
+ export const CLUSTER_SLUG = "statline";
3
+ export const VERSION = "0.1.0";
4
+ export const TOOLS = [
5
+ {
6
+ "name": "win-prob",
7
+ "http_name": "win-prob",
8
+ "description": "(0.003 USDC/call) Live sports win probability API / in-game win probability calculator / NFL NBA MLB NHL soccer win chance from current score and time remaining. Models the rest of the game as a random walk on the score margin (final margin = current margin + a normal increment whose mean is the pregame edge accrued over the time left and whose std dev is the sport's final-margin volatility scaled by sqrt of time remaining), then returns each team's win probability as the normal CDF of the projected final margin, plus projected final margin, the 1-sigma swing still possible, and human-readable drivers. Pure deterministic compute, no upstream API. Built-in scoring volatility for NFL/NCAAF/NBA/NCAAB/WNBA/MLB/NHL/soccer; override scoring_std for any sport. Statistical estimate, not betting advice.",
9
+ "method": "POST",
10
+ "input_schema": {
11
+ "type": "object",
12
+ "properties": {
13
+ "sport": {
14
+ "type": "string",
15
+ "description": "Sport/league: nfl, ncaaf, nba, ncaab, wnba, mlb, nhl, soccer/epl/mls. Case-insensitive. Use 'generic' with scoring_std for anything else."
16
+ },
17
+ "score_a": {
18
+ "type": "number",
19
+ "description": "Current score of team A (the reference team)."
20
+ },
21
+ "score_b": {
22
+ "type": "number",
23
+ "description": "Current score of team B."
24
+ },
25
+ "time_remaining_fraction": {
26
+ "type": "number",
27
+ "description": "Fraction of the game still to play, 0-1. Provide this OR minutes_remaining + minutes_total."
28
+ },
29
+ "minutes_remaining": {
30
+ "type": "number",
31
+ "description": "Game minutes left (alternative to time_remaining_fraction)."
32
+ },
33
+ "minutes_total": {
34
+ "type": "number",
35
+ "description": "Total game minutes (e.g. 48 NBA, 60 NFL/NHL)."
36
+ },
37
+ "pregame_spread": {
38
+ "type": "number",
39
+ "description": "Optional expected FINAL margin for team A at kickoff (positive = A favored). Default 0 (even)."
40
+ },
41
+ "scoring_std": {
42
+ "type": "number",
43
+ "description": "Optional override of the final-margin standard deviation; required for sports without a built-in default."
44
+ },
45
+ "team_a_name": {
46
+ "type": "string",
47
+ "description": "Optional label for team A."
48
+ },
49
+ "team_b_name": {
50
+ "type": "string",
51
+ "description": "Optional label for team B."
52
+ }
53
+ },
54
+ "required": [
55
+ "score_a",
56
+ "score_b"
57
+ ]
58
+ }
59
+ }
60
+ ];
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@agentutility/mcp-statline",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for the @agentutility statline cluster — pay-per-call x402 tools, no API keys, USDC on Base.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "bin": {
9
+ "agentutility-mcp-statline": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/rooz21/x402",
18
+ "directory": "packages/mcp-statline"
19
+ },
20
+ "homepage": "https://mcp.agentutility.ai/statline/",
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "model-context-protocol",
28
+ "x402",
29
+ "agentutility",
30
+ "agent-tools",
31
+ "statline"
32
+ ],
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.0.4",
35
+ "@x402/fetch": "^2.12.0",
36
+ "@x402/evm": "^2.12.0",
37
+ "viem": "^2.21.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^22.0.0",
41
+ "typescript": "^5.5.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ }
46
+ }