orchard-data-mcp 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.
Files changed (3) hide show
  1. package/README.md +51 -0
  2. package/package.json +45 -0
  3. package/server.mjs +100 -0
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # orchard-data-mcp
2
+
3
+ MCP server for [orchard-data](https://orchard-data.letom1176.workers.dev) — pay-per-call
4
+ market data for AI agents over [x402](https://x402.org) (USDC micro-payments on Base).
5
+
6
+ **The flagship tools are unique data**: an ML market-regime forecast, a news
7
+ catalyst radar, and a **live-verified track record** produced by a real
8
+ algorithmic trading system (the model actually trades), refreshed ~15 min
9
+ during US market hours, staleness always reported.
10
+
11
+ ## Tools
12
+
13
+ | Tool | Price/call | What |
14
+ |---|---|---|
15
+ | `list_products` | free | Product manifest |
16
+ | `get_regime_forecast` ⭐ | $0.01 | ML vol-regime forecast + transparent rules snapshot |
17
+ | `get_track_record` ⭐ | $0.01 | Live-verified system record + server-side scored forecast ledger |
18
+ | `get_catalyst_radar` ⭐ | $0.01 | Tickers with fresh bullish news catalysts |
19
+ | `get_market_brief` | $0.005 | BTC/ETH/SOL + SPY/QQQ/IWM/VIX + fear&greed |
20
+ | `get_trending` | $0.005 | StockTwits + WSB mentions |
21
+ | `get_movers` | $0.005 | Trending tickers w/ live quotes |
22
+ | `get_expected_move` | $0.005 | Options-implied expected move (ATM straddle) for any symbol |
23
+ | `get_macro` | $0.003 | Yields, DXY, gold, oil, VIX |
24
+ | `get_funding_rates` | $0.003 | BTC/ETH/SOL perp funding (OKX) |
25
+ | `get_ohlcv` | $0.002 | Daily candles, any symbol |
26
+ | `get_fear_greed` | $0.001 | Crypto fear & greed |
27
+
28
+ ## Setup
29
+
30
+ Payments need a small dedicated Base wallet holding USDC (a few dollars goes a
31
+ long way at these prices). **Use a burner wallet, never your main one.**
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "orchard-data": {
37
+ "command": "npx",
38
+ "args": ["-y", "orchard-data-mcp"],
39
+ "env": { "EVM_PRIVATE_KEY": "0x<burner wallet private key>" }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Without `EVM_PRIVATE_KEY`, `list_products` still works and paid tools explain setup.
46
+
47
+ ## How payment works
48
+
49
+ Each paid tool call: GET → HTTP 402 (payment requirements) → the server signs a
50
+ USDC transfer authorization with your key → retries → JSON. Settlement is
51
+ gasless for the buyer (EIP-3009 via the x402 facilitator). No account, no API key.
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "orchard-data-mcp",
3
+ "version": "1.1.0",
4
+ "description": "MCP server for orchard-data: pay-per-call market data for AI agents via x402 (USDC on Base). ML regime forecasts + live-verified track record from a real trading system, catalyst radar, quotes, macro, options expected move.",
5
+ "type": "module",
6
+ "bin": {
7
+ "orchard-data-mcp": "./server.mjs"
8
+ },
9
+ "files": [
10
+ "server.mjs",
11
+ "README.md"
12
+ ],
13
+ "engines": {
14
+ "node": ">=18"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "mcp-server",
19
+ "modelcontextprotocol",
20
+ "x402",
21
+ "market-data",
22
+ "trading",
23
+ "usdc",
24
+ "base",
25
+ "micropayments",
26
+ "ai-agents",
27
+ "regime-forecast",
28
+ "stocks",
29
+ "crypto"
30
+ ],
31
+ "author": "orchard-data",
32
+ "license": "MIT",
33
+ "homepage": "https://orchard-data.letom1176.workers.dev",
34
+ "scripts": {
35
+ "start": "node server.mjs",
36
+ "test": "node test-client.mjs"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.29.0",
40
+ "@x402/evm": "^2.18.0",
41
+ "@x402/fetch": "^2.18.0",
42
+ "viem": "^2.55.2",
43
+ "zod": "^4.4.3"
44
+ }
45
+ }
package/server.mjs ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ // orchard-data MCP server: exposes the paid x402 market-data API as MCP tools.
3
+ // Each paid tool call signs a USDC micro-payment (Base) with the wallet in
4
+ // EVM_PRIVATE_KEY and returns the JSON. Without a key, paid tools return
5
+ // clear setup instructions instead of failing cryptically.
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { z } from "zod";
9
+
10
+ const BASE = process.env.ORCHARD_BASE_URL || "https://orchard-data.letom1176.workers.dev";
11
+ const NETWORK = "eip155:8453"; // Base mainnet
12
+
13
+ let payFetch = null;
14
+ let walletAddress = null;
15
+ async function getPayFetch() {
16
+ if (payFetch) return payFetch;
17
+ const pk = process.env.EVM_PRIVATE_KEY;
18
+ if (!pk) return null;
19
+ const [{ wrapFetchWithPaymentFromConfig }, { ExactEvmScheme }, { privateKeyToAccount }] =
20
+ await Promise.all([import("@x402/fetch"), import("@x402/evm"), import("viem/accounts")]);
21
+ const account = privateKeyToAccount(pk.startsWith("0x") ? pk : `0x${pk}`);
22
+ walletAddress = account.address;
23
+ payFetch = wrapFetchWithPaymentFromConfig(fetch, {
24
+ schemes: [{ network: NETWORK, client: new ExactEvmScheme(account) }],
25
+ });
26
+ return payFetch;
27
+ }
28
+
29
+ const NO_KEY_MSG = `No payment wallet configured. Paid tools need a Base wallet holding a little USDC:
30
+ 1. Set env var EVM_PRIVATE_KEY to a Base wallet private key (0x...). Use a small dedicated wallet, NOT your main one.
31
+ 2. Fund it with USDC on Base (each call costs $0.001-0.01).
32
+ 3. Restart the MCP server.
33
+ The free tool list_products works without a key.`;
34
+
35
+ async function callPaid(path) {
36
+ const f = await getPayFetch();
37
+ if (!f) return { content: [{ type: "text", text: NO_KEY_MSG }], isError: true };
38
+ try {
39
+ const res = await f(`${BASE}${path}`, { headers: { Accept: "application/json" } });
40
+ const text = await res.text();
41
+ if (res.status !== 200) {
42
+ return {
43
+ content: [{ type: "text", text: `HTTP ${res.status} from ${path} (wallet ${walletAddress}). Body: ${text.slice(0, 600)}\nMost common cause: the wallet has no USDC on Base.` }],
44
+ isError: true,
45
+ };
46
+ }
47
+ return { content: [{ type: "text", text }] };
48
+ } catch (e) {
49
+ return { content: [{ type: "text", text: `Payment/call failed for ${path}: ${String(e?.message || e).slice(0, 500)}` }], isError: true };
50
+ }
51
+ }
52
+
53
+ const server = new McpServer({ name: "orchard-data", version: "1.1.0" });
54
+
55
+ server.registerTool(
56
+ "list_products",
57
+ { description: "FREE: list all orchard-data market-data endpoints with prices (x402/USDC on Base)." },
58
+ async () => {
59
+ const res = await fetch(`${BASE}/`, { headers: { Accept: "application/json" } });
60
+ return { content: [{ type: "text", text: await res.text() }] };
61
+ },
62
+ );
63
+
64
+ const paidTools = [
65
+ ["get_regime_forecast", "/api/regime-forecast", "US market regime read ($0.01): ML volatility-regime forecast from a live trading system (when fresh, with 'why') + transparent rules-based snapshot (VIX bands, realized-vol percentile, trend). Best single call for 'what kind of market is this?'"],
66
+ ["get_catalyst_radar", "/api/catalyst-radar", "Tickers with fresh bullish news catalysts ($0.01), from an AI news scanner feeding a live trading system. Refreshed ~15min during US market hours."],
67
+ ["get_market_brief", "/api/market-brief", "One-call market snapshot ($0.005): BTC/ETH/SOL spot + 24h change, crypto fear & greed, SPY/QQQ/IWM/VIX quotes."],
68
+ ["get_trending", "/api/trending", "Trending tickers ($0.005): StockTwits trending symbols + r/wallstreetbets mention counts with 24h momentum."],
69
+ ["get_movers", "/api/movers", "Top trending US tickers with live quotes ($0.005), sorted by absolute move."],
70
+ ["get_macro", "/api/macro", "Macro dashboard ($0.003): 13w/5y/10y/30y Treasury yields, dollar index, gold, WTI crude, VIX."],
71
+ ["get_fear_greed", "/api/fear-greed", "Crypto fear & greed index ($0.001), current + previous reading."],
72
+ ["get_track_record", "/api/track-record", "Live-verified trading-system track record ($0.01): normalized per-lane win rates, system-vs-SPY multiples, and a server-side scored forecast ledger (fixed disclosed rule vs realized SPY moves — grows daily, can't be faked)."],
73
+ ["get_funding_rates", "/api/funding-rates", "Perp funding rates ($0.003): BTC/ETH/SOL from OKX — crowded-side gauge for crypto positioning."],
74
+ ];
75
+
76
+ for (const [name, path, description] of paidTools) {
77
+ server.registerTool(name, { description }, async () => callPaid(path));
78
+ }
79
+
80
+ server.registerTool(
81
+ "get_ohlcv",
82
+ {
83
+ description: "Daily OHLCV candles for any US symbol ($0.002). range: 5d|1mo|3mo|6mo|1y.",
84
+ inputSchema: { symbol: z.string().describe("Ticker, e.g. SPY, NVDA"), range: z.enum(["5d", "1mo", "3mo", "6mo", "1y"]).optional() },
85
+ },
86
+ async ({ symbol, range }) =>
87
+ callPaid(`/api/ohlcv?symbol=${encodeURIComponent(symbol)}&range=${range || "1mo"}`),
88
+ );
89
+
90
+ server.registerTool(
91
+ "get_expected_move",
92
+ {
93
+ description: "Options-implied expected move for a US symbol ($0.005): nearest-expiry ATM straddle mid as a % of spot.",
94
+ inputSchema: { symbol: z.string().describe("Ticker, e.g. SPY, NVDA") },
95
+ },
96
+ async ({ symbol }) => callPaid(`/api/expected-move?symbol=${encodeURIComponent(symbol)}`),
97
+ );
98
+
99
+ const transport = new StdioServerTransport();
100
+ await server.connect(transport);