@agentutility/mcp-statline 0.1.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/README.md +74 -0
- package/dist/index.js +86 -0
- package/dist/tools.generated.js +60 -0
- package/package.json +46 -0
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 — from the current score and time, in one call.
|
|
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. Returns each team's win probability, the projected final margin, the size of the swing still possible, and human-readable drivers. 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.1 · **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.1";
|
|
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. Returns each team's win probability, the projected final margin, the size of the swing still possible, and human-readable drivers. 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.1",
|
|
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
|
+
}
|