@bxetech/bpe-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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BXETECH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # BPE MCP Server
2
+
3
+ Model Context Protocol server for the [BPE](https://bxetech.com) market-data
4
+ API. Lets Claude Desktop, Cursor, Goose, and other MCP-enabled agents query
5
+ consolidated Bitcoin pricing, ML signals, funding-rate skew, and
6
+ natural-language market briefings — without writing any HTTP boilerplate.
7
+
8
+ > **Status:** v0.1 prototype. Four tools, local stdio transport, no LLM
9
+ > calls inside the briefing endpoint (template-rendered). API key required.
10
+
11
+ ## Why use it
12
+
13
+ If you're building an agent that touches Bitcoin markets, you have two
14
+ options today:
15
+
16
+ 1. **Talk to 36 different exchange APIs directly.** Each has a different
17
+ schema, different auth, different rate limits, different reliability.
18
+ Your agent burns tokens reasoning over inconsistent payloads.
19
+ 2. **Use one consolidated source.** BPE aggregates all 36 venues into a
20
+ single normalised feed with derived signals (ML predictions,
21
+ sentiment, funding skew, basis). One auth, one schema, one tool call.
22
+
23
+ This MCP server is option 2 dressed up as native tools your agent can
24
+ discover and call.
25
+
26
+ ## Tools (v0.1)
27
+
28
+ | Tool | What it does |
29
+ |---|---|
30
+ | `get_consolidated_price` | Current BTC price aggregated across the BPE network |
31
+ | `get_market_briefing` | 5–8 line natural-language market summary (price, funding, ML, sentiment, anomalies) |
32
+ | `get_funding_skew` | Per-venue annualised funding rates + max-spread pair |
33
+ | `get_ml_signal` | Current ML prediction across configurable time horizons |
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ npm install -g @bxetech/bpe-mcp
39
+ ```
40
+
41
+ Or use `npx` with no install (recommended for Claude Desktop):
42
+
43
+ ```jsonc
44
+ // ~/Library/Application Support/Claude/claude_desktop_config.json
45
+ {
46
+ "mcpServers": {
47
+ "bpe": {
48
+ "command": "npx",
49
+ "args": ["-y", "@bxetech/bpe-mcp"],
50
+ "env": {
51
+ "BPE_API_KEY": "bpe_..."
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ Restart Claude Desktop. The four tools appear under the MCP server picker.
59
+
60
+ ## Configuration
61
+
62
+ | Env var | Default | Notes |
63
+ |---|---|---|
64
+ | `BPE_API_KEY` | *(required)* | Get one at https://bxetech.com/contact |
65
+ | `BPE_BASE_URL` | `https://mcp.bxetech.com` | Override for self-hosted / local dev |
66
+ | `BPE_TIMEOUT_MS` | `5000` | Per-request timeout |
67
+
68
+ ## Local development
69
+
70
+ ```bash
71
+ git clone https://github.com/bxetech/bpe-mcp
72
+ cd bpe-mcp
73
+ npm install
74
+ npm run build
75
+ BPE_API_KEY=... npm run dev
76
+ ```
77
+
78
+ To dogfood in Claude Desktop while iterating, point at the local build:
79
+
80
+ ```jsonc
81
+ {
82
+ "mcpServers": {
83
+ "bpe-dev": {
84
+ "command": "node",
85
+ "args": ["/abs/path/to/mcp-server/dist/index.js"],
86
+ "env": {
87
+ "BPE_API_KEY": "...",
88
+ "BPE_BASE_URL": "http://localhost:8082"
89
+ }
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ ## Roadmap
96
+
97
+ - **v0.2** — `get_basis`, `get_sentiment_snapshot`, `subscribe_alert` (webhook subscription)
98
+ - **v0.3** — Hosted HTTP transport for non-developer install (Cursor extension, ChatGPT Desktop)
99
+ - **v0.4** — Optional LLM-rendered briefing via Haiku (richer prose, with per-call cost)
100
+
101
+ See [`docs/research/AGENT_INTEGRATION_AND_MONETISATION_2026-04-27.md`](../docs/research/AGENT_INTEGRATION_AND_MONETISATION_2026-04-27.md) for the broader product / monetisation plan.
102
+
103
+ ## License
104
+
105
+ MIT — see [`LICENSE`](./LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,67 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ If you believe you have found a security vulnerability in this MCP
6
+ server, **please do not open a public GitHub issue.** Instead, report it
7
+ privately so we can investigate and ship a fix before details become
8
+ public.
9
+
10
+ **Preferred channel:** GitHub Security Advisory — open a draft advisory
11
+ on this repository under the *Security* tab → *Advisories* → *Report a
12
+ vulnerability*. This routes the report directly to the maintainers and
13
+ is invisible to anyone else until we publish.
14
+
15
+ **Alternative:** email <security@bxetech.com> with a description of the
16
+ issue and steps to reproduce. PGP encryption available on request.
17
+
18
+ ## Scope
19
+
20
+ In scope:
21
+
22
+ - This npm package (`@bxetech/bpe-mcp`) and its installation flow.
23
+ - The protocol-level interaction between the MCP server and any
24
+ upstream BPE API endpoints it calls on behalf of the user.
25
+ - API-key handling on the local machine where the MCP server runs.
26
+
27
+ Out of scope (handled separately):
28
+
29
+ - The BPE API itself (`api.bxetech.com`) — report at
30
+ <security@bxetech.com> with subject prefix `[BPE API]`.
31
+ - The BXETECH website (`bxetech.com`) — same address, prefix
32
+ `[BXETECH website]`.
33
+ - Issues affecting Anthropic's Claude Desktop, Cursor, or other MCP
34
+ clients themselves — report to those vendors directly.
35
+
36
+ ## What we ask
37
+
38
+ - Provide enough detail for us to reproduce the issue.
39
+ - Don't exploit the vulnerability beyond what is needed to demonstrate
40
+ it.
41
+ - Don't access, modify, or delete data belonging to other BPE API
42
+ customers.
43
+ - Give us reasonable time to fix the issue before public disclosure
44
+ (typically 90 days, faster for critical issues).
45
+
46
+ ## What you can expect
47
+
48
+ - Acknowledgement within 3 business days.
49
+ - A status update within 10 business days, including whether the issue
50
+ is accepted, deferred, or out of scope.
51
+ - Credit in the release notes when a fix ships, unless you'd prefer to
52
+ remain anonymous.
53
+
54
+ ## Known limitations
55
+
56
+ The v0.1 release does not currently:
57
+
58
+ - Validate webhook subscription URLs against SSRF (the
59
+ `subscribe_alert` tool ships in v0.2; SSRF protections will land at
60
+ the same time).
61
+ - Encrypt API keys at rest within MCP client config files (this is a
62
+ property of the host MCP client, e.g. Claude Desktop, not of this
63
+ package).
64
+
65
+ These are tracked publicly in the issue tracker and in the
66
+ [`AGENT_INTEGRATION_AND_MONETISATION_2026-04-27.md`](https://bxetech.com/agents)
67
+ research note.
package/SKILL.md ADDED
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: bpe-market-intelligence
3
+ version: 0.1.0
4
+ description: Cross-venue Bitcoin market intelligence — consolidated pricing, ML signals, funding-rate skew, sentiment, and natural-language briefings across 36 exchanges. Companion to single-exchange MCPs.
5
+ homepage: https://bxetech.com/agents
6
+ license: MIT
7
+ ---
8
+
9
+ # BPE Market Intelligence
10
+
11
+ A skill for AI agents that need to reason about Bitcoin markets across
12
+ venues. Pairs naturally with single-exchange MCP servers (Bybit,
13
+ Coinbase, Gemini, Kraken, OKX) — those handle execution on one venue;
14
+ BPE handles cross-venue intelligence.
15
+
16
+ ## When to use this skill
17
+
18
+ Reach for BPE tools when the agent's task involves any of:
19
+
20
+ - **"What's BTC doing right now?"** → call `get_market_briefing` first.
21
+ One call replaces dozens of raw-data calls plus the synthesis work.
22
+ - **Spread / arbitrage / basis questions** → `get_funding_skew` for
23
+ perp-perp; the briefing endpoint surfaces consolidated-vs-venue
24
+ divergence.
25
+ - **Directional questions** ("is the market bullish?", "should I expect
26
+ mean-reversion?") → `get_ml_signal` returns calibrated probability,
27
+ not just direction.
28
+ - **Reconciling a position against the broader market** → if the user
29
+ is on a single exchange and asks why their P&L looks the way it does,
30
+ cross-check the venue's price against `get_consolidated_price`.
31
+ - **Anomaly detection** → the briefing's anomaly hint flags extreme
32
+ funding spreads or high ML confidence regimes worth investigating.
33
+
34
+ ## When NOT to use this skill
35
+
36
+ - **Order routing, fills, balances, withdrawals** → use the user's
37
+ exchange MCP (Bybit, Coinbase, etc.). BPE is read-only and has
38
+ no execution surface.
39
+ - **Exchange-specific account state** ("what's my Bybit balance?") →
40
+ exchange MCP, not BPE. We don't have visibility into user accounts.
41
+ - **Wallet operations, signing, on-chain** → not this skill.
42
+
43
+ ## Recommended call patterns
44
+
45
+ ### Pattern 1 — orient before drilling down
46
+
47
+ For open-ended market questions, **always call `get_market_briefing`
48
+ first**. It costs ~1 rate-limit token and ~50 tokens of context, and
49
+ gives the agent enough situational awareness to decide what (if
50
+ anything) to drill into next. Avoid making the agent assemble a
51
+ briefing from individual `get_consolidated_price` / `get_funding_skew`
52
+ / `get_ml_signal` calls — that's slower, more expensive, and what
53
+ the briefing endpoint exists to prevent.
54
+
55
+ ### Pattern 2 — confidence-gated decision-making
56
+
57
+ `get_ml_signal` returns calibrated probabilities. Confidence is on a
58
+ 0–1 scale where:
59
+
60
+ - **< 0.55** — treat as noise. The model has a slight edge but not
61
+ enough to justify a thesis.
62
+ - **0.55–0.70** — directionally interesting. Worth combining with other
63
+ signals (funding skew, sentiment, regime) before acting.
64
+ - **> 0.70** — high-conviction. Surfaced as an anomaly in the briefing.
65
+ - **> 0.85** — rare; the model is unusually confident. Worth flagging
66
+ to the user explicitly.
67
+
68
+ Don't treat confidence as binary. Don't translate "up" / "down" into
69
+ trade signals without considering the magnitude.
70
+
71
+ ### Pattern 3 — companion to an exchange MCP
72
+
73
+ When the user has both an exchange MCP and BPE installed:
74
+
75
+ - Use **the exchange MCP** for: order placement, account state, fills,
76
+ balance queries, withdrawals.
77
+ - Use **BPE** for: pre-trade context (is the market right for this
78
+ trade?), post-trade reconciliation (did my venue's price match
79
+ consensus?), strategy ideation (where's funding cheapest?).
80
+ - **Never confuse the two.** A BPE call that reads `get_consolidated_price`
81
+ doesn't reflect the price the user can actually execute at on their
82
+ venue. Use the exchange MCP's order-book or quote tools for that.
83
+
84
+ ## Tool reference
85
+
86
+ | Tool | Use when | Cost |
87
+ |---|---|---|
88
+ | `get_market_briefing` | Default first call for any open-ended market question | 1 rate-limit token |
89
+ | `get_consolidated_price` | "What's BTC at right now?" | 1 token |
90
+ | `get_funding_skew` | Perp-perp arb, basis trade ideation, positioning skew analysis | 1 token |
91
+ | `get_ml_signal` | Directional questions, regime detection | 1 token |
92
+
93
+ All tools return text content blocks designed for direct consumption
94
+ by the LLM. No JSON parsing required.
95
+
96
+ ## Available time horizons
97
+
98
+ `get_ml_signal` accepts `30s`, `60s`, `5m`. Available horizons may
99
+ evolve over time — if the agent receives an "available horizons"
100
+ error, it should retry with one of the listed alternatives.
101
+
102
+ ## Limitations to surface to the user
103
+
104
+ - **Read-only.** BPE cannot place orders, manage positions, or move
105
+ funds. If the user asks the agent to act on a signal, route through
106
+ their exchange MCP.
107
+ - **BTC-only in v0.1.** ETH, SOL, and other assets are out of scope.
108
+ If the user asks about another asset, say so plainly.
109
+ - **ML signal is a probability, not a guarantee.** The model is well-
110
+ calibrated but markets remain noisy. Frame predictions as "the model
111
+ thinks X is more likely than Y", not "X will happen".
112
+
113
+ ## Background
114
+
115
+ BPE (Bitcoin Pricing Engine) consolidates 36 exchanges into a single
116
+ normalised market-data feed with sub-100µs internal latency, plus
117
+ derived intelligence layers: a calibrated gradient-boosted ML model
118
+ trained on a broad engineered feature set, sentiment indicators
119
+ (Fear & Greed, news, mempool stress), and cross-venue funding /
120
+ basis analysis. Running in production for institutional users; the
121
+ MCP server exposes this as native agent tools.
@@ -0,0 +1,3 @@
1
+ import type { BpeClient } from "./client.js";
2
+ export type BriefingVerbosity = "brief" | "detailed";
3
+ export declare function buildBriefing(client: BpeClient, verbosity: BriefingVerbosity): Promise<string>;
@@ -0,0 +1,137 @@
1
+ // Briefing endpoint synthesiser.
2
+ //
3
+ // v0.1 strategy: call the api-gateway's bundled /briefing endpoint, which
4
+ // returns price + derivatives + predictions + sentiment in a single
5
+ // envelope. Fold into a deterministic natural-language template. No LLM
6
+ // involved — that's a v0.2 upgrade if we want richer summaries.
7
+ //
8
+ // Why deterministic first:
9
+ // - zero per-call cost, no LLM dependency
10
+ // - predictable output shape (easier for downstream agents to parse)
11
+ // - we can A/B against an LLM-rendered version later
12
+ //
13
+ // Why the bundled endpoint vs 4 separate calls:
14
+ // - 1 rate-limit token per briefing (was 4)
15
+ // - 1 HTTP round-trip (was 4)
16
+ // - server filters by tier permissions, so Free callers receive a
17
+ // partial bundle (graceful degradation) rather than 4× 403s
18
+ // - underlying channels are read from the gateway's in-memory cache,
19
+ // so freshness is identical to the per-channel endpoints
20
+ export async function buildBriefing(client, verbosity) {
21
+ // Single bundled call — replaces the 4-channel fan-out.
22
+ let bundle;
23
+ try {
24
+ bundle = await client.get("briefing");
25
+ }
26
+ catch {
27
+ bundle = {};
28
+ }
29
+ // Re-pack as Promise.allSettled-shaped results so the rest of the
30
+ // synthesis code can stay unchanged.
31
+ const wrap = (v) => v != null
32
+ ? { status: "fulfilled", value: v }
33
+ : { status: "rejected", reason: new Error("not in bundle") };
34
+ const price = wrap(bundle.price);
35
+ const derivs = wrap(bundle.derivatives);
36
+ const preds = wrap(bundle.predictions);
37
+ const sent = wrap(bundle.sentiment);
38
+ const lines = [];
39
+ // Price line
40
+ if (price.status === "fulfilled" && price.value?.price) {
41
+ const p = price.value;
42
+ const venues = p.exchange_count ?? "?";
43
+ const ageMs = p.timestamp_ms != null ? Math.max(0, Date.now() - p.timestamp_ms) : null;
44
+ const ageStr = ageMs == null ? "fresh" : ageMs < 1000 ? `${ageMs} ms old` : `${(ageMs / 1000).toFixed(1)}s old`;
45
+ lines.push(`BTC: $${formatPrice(p.price)} (consolidated across ${venues} exchanges, ${ageStr}).`);
46
+ }
47
+ else {
48
+ lines.push("BTC price: unavailable.");
49
+ }
50
+ // Funding skew
51
+ if (derivs.status === "fulfilled" && derivs.value?.funding_rates?.length) {
52
+ const rates = derivs.value.funding_rates
53
+ .filter((r) => Number.isFinite(r.annualized_rate ?? r.funding_rate * 3 * 365))
54
+ .map((r) => ({
55
+ ex: r.exchange,
56
+ ann: r.annualized_rate ?? r.funding_rate * 3 * 365,
57
+ }));
58
+ if (rates.length >= 2) {
59
+ rates.sort((a, b) => b.ann - a.ann);
60
+ const top = rates[0];
61
+ const bot = rates[rates.length - 1];
62
+ const spread = top.ann - bot.ann;
63
+ lines.push(`Funding skew: ${top.ex} ${formatPct(top.ann)} APR vs ${bot.ex} ${formatPct(bot.ann)} APR — spread ${formatPct(spread)} APR.`);
64
+ if (verbosity === "detailed") {
65
+ const detail = rates
66
+ .slice(0, 6)
67
+ .map((r) => `${r.ex} ${formatPct(r.ann)}`)
68
+ .join(", ");
69
+ lines.push(` All venues: ${detail}.`);
70
+ }
71
+ }
72
+ }
73
+ // ML signal — server returns a single prediction snapshot (whichever
74
+ // horizon the upstream pricing-service most recently emitted).
75
+ if (preds.status === "fulfilled" && preds.value?.direction) {
76
+ const p = preds.value;
77
+ const horizon = p.horizon_secs != null ? `${p.horizon_secs}s` : "?";
78
+ const conf = p.confidence != null ? ` (${(p.confidence * 100).toFixed(0)}% confidence)` : "";
79
+ const prob = p.probability != null ? `, p=${(p.probability * 100).toFixed(0)}%` : "";
80
+ lines.push(`ML ${horizon}: ${p.direction}${conf}${prob}.`);
81
+ if (verbosity === "detailed" && p.models?.length) {
82
+ const detail = p.models
83
+ .map((m) => `${m.name}${m.signal != null ? `=${m.signal.toFixed(3)}` : ""}`)
84
+ .join(", ");
85
+ lines.push(` Sub-models: ${detail}.`);
86
+ }
87
+ }
88
+ // Sentiment
89
+ if (sent.status === "fulfilled") {
90
+ const s = sent.value;
91
+ const parts = [];
92
+ if (s?.fear_greed_index != null) {
93
+ parts.push(`F&G ${s.fear_greed_index}${s.fear_greed_label ? ` (${s.fear_greed_label})` : ""}`);
94
+ }
95
+ if (s?.news_sentiment != null)
96
+ parts.push(`news ${s.news_sentiment.toFixed(2)}`);
97
+ if (s?.mempool_stress != null)
98
+ parts.push(`mempool ${s.mempool_stress.toFixed(2)}`);
99
+ if (parts.length)
100
+ lines.push(`Sentiment: ${parts.join(", ")}.`);
101
+ }
102
+ // Anomaly hint — only thing computed locally (over the data we just pulled)
103
+ const anomaly = detectAnomaly(derivs, preds);
104
+ if (anomaly)
105
+ lines.push(`Anomaly: ${anomaly}`);
106
+ return lines.join("\n");
107
+ }
108
+ // Cheap heuristics — flag obvious abnormalities so the agent doesn't have to
109
+ // reason them out.
110
+ function detectAnomaly(derivs, preds) {
111
+ if (derivs.status === "fulfilled" && derivs.value?.funding_rates) {
112
+ const ann = derivs.value.funding_rates
113
+ .map((r) => r.annualized_rate ?? r.funding_rate * 3 * 365)
114
+ .filter((x) => Number.isFinite(x));
115
+ const max = ann.length ? Math.max(...ann) : 0;
116
+ const min = ann.length ? Math.min(...ann) : 0;
117
+ if (max - min > 0.25)
118
+ return `funding spread ${formatPct(max - min)} APR (>25% — basis or perp-perp arb opportunity).`;
119
+ if (Math.abs(max) > 0.5)
120
+ return `extreme funding ${formatPct(max)} APR — perp positioning stretched.`;
121
+ }
122
+ if (preds.status === "fulfilled" && preds.value?.direction) {
123
+ const p = preds.value;
124
+ if ((p.confidence ?? 0) > 0.85) {
125
+ const horizon = p.horizon_secs != null ? `${p.horizon_secs}s` : "current";
126
+ return `ML confidence ${(p.confidence * 100).toFixed(0)}% on ${horizon} horizon (${p.direction}).`;
127
+ }
128
+ }
129
+ return null;
130
+ }
131
+ function formatPrice(n) {
132
+ return n >= 1000 ? n.toLocaleString("en-US", { maximumFractionDigits: 0 }) : n.toFixed(2);
133
+ }
134
+ function formatPct(frac) {
135
+ return `${(frac * 100).toFixed(2)}%`;
136
+ }
137
+ //# sourceMappingURL=briefing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"briefing.js","sourceRoot":"","sources":["../src/briefing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ export declare class BpeApiError extends Error {
2
+ readonly status?: number | undefined;
3
+ readonly endpoint?: string | undefined;
4
+ constructor(message: string, status?: number | undefined, endpoint?: string | undefined);
5
+ }
6
+ export declare class BpeClient {
7
+ private readonly baseUrl;
8
+ private readonly apiKey;
9
+ private readonly timeoutMs;
10
+ constructor(opts: {
11
+ baseUrl?: string;
12
+ apiKey: string;
13
+ timeoutMs?: number;
14
+ });
15
+ get<T = unknown>(path: string): Promise<T>;
16
+ }
17
+ export interface PriceResponse {
18
+ price: number;
19
+ best_bid?: number;
20
+ best_ask?: number;
21
+ spread_bps?: number;
22
+ confidence?: number;
23
+ exchange_count?: number;
24
+ sequence?: number;
25
+ timestamp_ms?: number;
26
+ symbol?: string;
27
+ }
28
+ export interface FundingRateEntry {
29
+ exchange: string;
30
+ funding_rate: number;
31
+ next_funding_time?: number;
32
+ annualized_rate?: number;
33
+ }
34
+ export interface DerivativesResponse {
35
+ funding_rates?: FundingRateEntry[];
36
+ open_interest?: Array<{
37
+ exchange: string;
38
+ oi_btc: number;
39
+ oi_usd?: number;
40
+ }>;
41
+ timestamp_ms?: number;
42
+ }
43
+ export interface PredictionsResponse {
44
+ horizon_secs?: number;
45
+ direction?: "up" | "down" | "flat";
46
+ probability?: number;
47
+ confidence?: number;
48
+ signal?: number;
49
+ risk_adjusted_signal?: number;
50
+ position_scale?: number;
51
+ volatility_forecast?: number;
52
+ models?: Array<{
53
+ name: string;
54
+ signal?: number;
55
+ confidence?: number;
56
+ }>;
57
+ timestamp_ms?: number;
58
+ }
59
+ export interface SentimentResponse {
60
+ fear_greed_index?: number;
61
+ fear_greed_label?: string;
62
+ news_sentiment?: number;
63
+ mempool_stress?: number;
64
+ timestamp_ms?: number;
65
+ }
package/dist/client.js ADDED
@@ -0,0 +1,68 @@
1
+ // Thin HTTP client for the BPE api-gateway. One file, no class hierarchy —
2
+ // each tool calls the channel it needs.
3
+ //
4
+ // Backend lives at the api-gateway (port 8082 in dev, https://mcp.bxetech.com
5
+ // in prod). Auth is an `X-API-Key` header — same key the dashboard / portal
6
+ // uses, supplied by the user via env or MCP server config.
7
+ //
8
+ // Why mcp.bxetech.com (not api.bxetech.com): the agent-facing endpoint is
9
+ // brand-separated from the (future) human-facing API SKU. Same backend
10
+ // today; lets us diverge later (dedicated MCP-shaped service, different
11
+ // rate-limit policy, etc.) without forcing customers to migrate.
12
+ const DEFAULT_BASE_URL = "https://mcp.bxetech.com";
13
+ export class BpeApiError extends Error {
14
+ status;
15
+ endpoint;
16
+ constructor(message, status, endpoint) {
17
+ super(message);
18
+ this.status = status;
19
+ this.endpoint = endpoint;
20
+ this.name = "BpeApiError";
21
+ }
22
+ }
23
+ export class BpeClient {
24
+ baseUrl;
25
+ apiKey;
26
+ timeoutMs;
27
+ constructor(opts) {
28
+ this.baseUrl = (opts.baseUrl ?? process.env.BPE_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
29
+ this.apiKey = opts.apiKey;
30
+ this.timeoutMs = opts.timeoutMs ?? 5_000;
31
+ }
32
+ // GET /api/v1/<path>. Returns the unwrapped `data` payload from the
33
+ // gateway's ApiEnvelope ({channel, seq, timestamp, snapshot, data}).
34
+ // Throws BpeApiError on non-2xx, network failure, or timeout.
35
+ async get(path) {
36
+ const url = `${this.baseUrl}/api/v1/${path.replace(/^\//, "")}`;
37
+ const ctrl = new AbortController();
38
+ const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);
39
+ try {
40
+ const res = await fetch(url, {
41
+ method: "GET",
42
+ headers: { "X-API-Key": this.apiKey, Accept: "application/json" },
43
+ signal: ctrl.signal,
44
+ });
45
+ if (!res.ok) {
46
+ const body = await res.text().catch(() => "");
47
+ throw new BpeApiError(`BPE API ${res.status} on /${path}: ${body.slice(0, 200)}`, res.status, path);
48
+ }
49
+ const json = (await res.json());
50
+ // Every gateway endpoint wraps in an ApiEnvelope. Unwrap `data` so
51
+ // callers receive the channel-specific payload directly.
52
+ if (json && typeof json === "object" && "data" in json) {
53
+ return json.data;
54
+ }
55
+ return json;
56
+ }
57
+ catch (err) {
58
+ if (err instanceof BpeApiError)
59
+ throw err;
60
+ const msg = err instanceof Error ? err.message : String(err);
61
+ throw new BpeApiError(`BPE API request failed on /${path}: ${msg}`, undefined, path);
62
+ }
63
+ finally {
64
+ clearTimeout(timer);
65
+ }
66
+ }
67
+ }
68
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ // BPE MCP server — entry point.
3
+ //
4
+ // Boots a stdio-transport MCP server that exposes the BPE market-data API
5
+ // to MCP-enabled agents (Claude Desktop, Cursor, Goose, etc.). All real
6
+ // work happens in tools.ts; this file just wires transport + lifecycle.
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { BpeClient } from "./client.js";
10
+ import { registerTools } from "./tools.js";
11
+ async function main() {
12
+ const apiKey = process.env.BPE_API_KEY;
13
+ if (!apiKey) {
14
+ // We can't write to stdout (it's the MCP transport), so log to stderr —
15
+ // Claude Desktop surfaces stderr in the MCP server logs panel.
16
+ process.stderr.write("Error: BPE_API_KEY environment variable is required.\n" +
17
+ "Get a key at https://bxetech.com/contact and set it in your\n" +
18
+ "MCP server config under `env.BPE_API_KEY`.\n");
19
+ process.exit(1);
20
+ }
21
+ const client = new BpeClient({
22
+ apiKey,
23
+ baseUrl: process.env.BPE_BASE_URL,
24
+ timeoutMs: process.env.BPE_TIMEOUT_MS ? Number(process.env.BPE_TIMEOUT_MS) : undefined,
25
+ });
26
+ const server = new McpServer({ name: "bpe", version: "0.1.0" }, { capabilities: { tools: {} } });
27
+ registerTools(server, client);
28
+ const transport = new StdioServerTransport();
29
+ await server.connect(transport);
30
+ // Don't log on successful boot — Claude Desktop only shows stderr if it
31
+ // looks like an error, and a routine "started" line trips false-positive
32
+ // warnings in the UI.
33
+ }
34
+ main().catch((err) => {
35
+ process.stderr.write(`bpe-mcp fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
36
+ process.exit(1);
37
+ });
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,gCAAgC;AAChC,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,wEAAwE;AAExE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,wEAAwE;QACxE,+DAA+D;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wDAAwD;YACtD,+DAA+D;YAC/D,8CAA8C,CACjD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QACjC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS;KACvF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EACjC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,wEAAwE;IACxE,yEAAyE;IACzE,sBAAsB;AACxB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type BpeClient } from "./client.js";
3
+ export declare function registerTools(server: McpServer, client: BpeClient): void;
package/dist/tools.js ADDED
@@ -0,0 +1,151 @@
1
+ // MCP tool registrations.
2
+ //
3
+ // v0.1 ships 4 tools (functions 1, 2, 3, 5 from the research note's §3.1):
4
+ // get_consolidated_price — current consolidated BTC price
5
+ // get_market_briefing — natural-language synthesis of 4 channels
6
+ // get_funding_skew — cross-venue funding rates + max-spread pair
7
+ // get_ml_signal — current ML prediction for a given horizon
8
+ //
9
+ // Stretch (v0.2): get_basis, get_sentiment_snapshot, subscribe_alert.
10
+ import { z } from "zod";
11
+ import { buildBriefing } from "./briefing.js";
12
+ // All tools return a single text content block. Returning structured JSON
13
+ // would also work, but text is the most agent-portable shape — every model
14
+ // handles it natively, and we can always graduate to structured output later.
15
+ function asText(text) {
16
+ return { content: [{ type: "text", text }] };
17
+ }
18
+ function asError(text) {
19
+ return { content: [{ type: "text", text }], isError: true };
20
+ }
21
+ export function registerTools(server, client) {
22
+ // ── 1. get_consolidated_price ────────────────────────────────────────────
23
+ server.tool("get_consolidated_price", "Get the current consolidated Bitcoin price aggregated across the BPE exchange network. Returns price in USD, the number of contributing exchanges, and freshness in milliseconds. Use this when an agent or user asks 'what's the BTC price right now?' — it's faster and more authoritative than calling any individual exchange.", {
24
+ symbol: z
25
+ .enum(["BTC-USD"])
26
+ .default("BTC-USD")
27
+ .describe("Trading pair. Currently only BTC-USD is supported."),
28
+ }, async ({ symbol }) => {
29
+ try {
30
+ const r = await client.get("price");
31
+ const venues = r.exchange_count ?? "?";
32
+ const ageMs = r.timestamp_ms != null ? Math.max(0, Date.now() - r.timestamp_ms) : null;
33
+ const ageStr = ageMs == null ? "n/a" : ageMs < 1000 ? `${ageMs}ms` : `${(ageMs / 1000).toFixed(1)}s`;
34
+ const lines = [`${symbol}: $${formatPrice(r.price)}`];
35
+ if (r.best_bid != null && r.best_ask != null) {
36
+ lines.push(`Bid/Ask: $${formatPrice(r.best_bid)} / $${formatPrice(r.best_ask)}` +
37
+ (r.spread_bps != null ? ` (${r.spread_bps.toFixed(1)} bps spread)` : ""));
38
+ }
39
+ lines.push(`Source: ${venues} exchanges contributing, ${ageStr} old` +
40
+ (r.confidence != null ? `, confidence ${(r.confidence * 100).toFixed(0)}%` : "") + ".");
41
+ return asText(lines.join("\n"));
42
+ }
43
+ catch (err) {
44
+ return asError(`Failed to fetch consolidated price: ${errMsg(err)}`);
45
+ }
46
+ });
47
+ // ── 2. get_market_briefing ───────────────────────────────────────────────
48
+ server.tool("get_market_briefing", "Get a concise natural-language summary of the current Bitcoin market state. Synthesises consolidated price, funding-rate skew across major perpetual venues, current ML prediction, and sentiment indicators into a 5-8 line briefing. This is the most token-efficient way for an agent to get the 'what's happening right now' picture — replaces 4-5 raw data calls plus the reasoning to summarise them. Set verbosity='detailed' for per-venue funding breakdown and multi-horizon ML signals.", {
49
+ verbosity: z
50
+ .enum(["brief", "detailed"])
51
+ .default("brief")
52
+ .describe("'brief' returns a 5-line headline summary; 'detailed' adds per-venue and multi-horizon breakdowns."),
53
+ }, async ({ verbosity }) => {
54
+ try {
55
+ const briefing = await buildBriefing(client, verbosity);
56
+ return asText(briefing);
57
+ }
58
+ catch (err) {
59
+ return asError(`Failed to build market briefing: ${errMsg(err)}`);
60
+ }
61
+ });
62
+ // ── 3. get_funding_skew ──────────────────────────────────────────────────
63
+ server.tool("get_funding_skew", "Get current perpetual-futures funding rates across major venues, plus the max-spread pair. Annualised. Useful for assessing perp-perp arbitrage conditions, basis trades, and overall positioning skew — high spread = stretched positioning on one side. Returns a sorted table.", {}, async () => {
64
+ try {
65
+ const r = await client.get("derivatives");
66
+ const rates = (r.funding_rates ?? [])
67
+ .map((f) => ({
68
+ ex: f.exchange,
69
+ ann: f.annualized_rate ?? f.funding_rate * 3 * 365,
70
+ }))
71
+ .filter((r) => Number.isFinite(r.ann))
72
+ .sort((a, b) => b.ann - a.ann);
73
+ if (!rates.length) {
74
+ return asError("No funding rate data available right now.");
75
+ }
76
+ const top = rates[0];
77
+ const bot = rates[rates.length - 1];
78
+ const spread = top.ann - bot.ann;
79
+ const lines = [];
80
+ lines.push(`Funding spread: ${formatPct(spread)} APR (${top.ex} ↔ ${bot.ex})`);
81
+ lines.push("");
82
+ lines.push("Per-venue annualised funding rates:");
83
+ for (const r of rates) {
84
+ lines.push(` ${r.ex.padEnd(20)} ${formatPct(r.ann)}`);
85
+ }
86
+ return asText(lines.join("\n"));
87
+ }
88
+ catch (err) {
89
+ return asError(`Failed to fetch funding skew: ${errMsg(err)}`);
90
+ }
91
+ });
92
+ // ── 4. get_ml_signal ─────────────────────────────────────────────────────
93
+ server.tool("get_ml_signal", "Get the current ML prediction for a specified time horizon. Returns direction (up/down/flat), confidence (0-1), and detected market regime (low/medium/high volatility). The model is a calibrated gradient-boosted classifier trained on a broad feature set including order book imbalance, cross-exchange spreads, sentiment, derivatives, and momentum.", {
94
+ horizon: z
95
+ .enum(["30s", "60s", "5m"])
96
+ .default("30s")
97
+ .describe("Prediction horizon. Shorter horizons are more reactive; longer horizons are more stable. Available horizons may evolve over time — the tool will report which horizons are currently served if a requested one is unavailable."),
98
+ }, async ({ horizon }) => {
99
+ try {
100
+ const requestedSecs = horizon === "30s" ? 30 : horizon === "60s" ? 60 : 300;
101
+ const r = await client.get("predictions");
102
+ if (r.direction == null && r.signal == null) {
103
+ return asError("No ML prediction currently available — try again in a few seconds.");
104
+ }
105
+ const lines = [];
106
+ const servedSecs = r.horizon_secs ?? null;
107
+ if (servedSecs != null && servedSecs !== requestedSecs) {
108
+ lines.push(`Note: requested ${horizon} horizon, server returned ${servedSecs}s (only one horizon is cached at a time in v0.1).`);
109
+ }
110
+ lines.push(`Horizon: ${servedSecs != null ? servedSecs + "s" : horizon}`);
111
+ if (r.direction)
112
+ lines.push(`Direction: ${r.direction}`);
113
+ if (r.probability != null) {
114
+ lines.push(`Probability: ${(r.probability * 100).toFixed(1)}%`);
115
+ }
116
+ if (r.confidence != null) {
117
+ lines.push(`Confidence: ${(r.confidence * 100).toFixed(1)}%`);
118
+ }
119
+ if (r.signal != null)
120
+ lines.push(`Signal: ${r.signal.toFixed(4)}`);
121
+ if (r.risk_adjusted_signal != null) {
122
+ lines.push(`Risk-adjusted signal: ${r.risk_adjusted_signal.toFixed(4)}`);
123
+ }
124
+ if (r.position_scale != null) {
125
+ lines.push(`Position scale: ${r.position_scale.toFixed(2)}`);
126
+ }
127
+ if (r.volatility_forecast != null) {
128
+ lines.push(`Volatility forecast: ${r.volatility_forecast.toFixed(4)}`);
129
+ }
130
+ if (r.models?.length) {
131
+ const summaries = r.models.map((m) => `${m.name}=${m.signal != null ? m.signal.toFixed(3) : "?"}` +
132
+ (m.confidence != null ? `@${(m.confidence * 100).toFixed(0)}%` : ""));
133
+ lines.push(`Sub-models: ${summaries.join(", ")}`);
134
+ }
135
+ return asText(lines.join("\n"));
136
+ }
137
+ catch (err) {
138
+ return asError(`Failed to fetch ML signal: ${errMsg(err)}`);
139
+ }
140
+ });
141
+ }
142
+ function formatPrice(n) {
143
+ return n >= 1000 ? n.toLocaleString("en-US", { maximumFractionDigits: 0 }) : n.toFixed(2);
144
+ }
145
+ function formatPct(frac) {
146
+ return `${(frac * 100).toFixed(2)}%`;
147
+ }
148
+ function errMsg(err) {
149
+ return err instanceof Error ? err.message : String(err);
150
+ }
151
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@bxetech/bpe-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for the BPE (Bitcoin Pricing Engine) market-data API. Lets Claude Desktop, Cursor, and other MCP-enabled agents query consolidated BTC pricing, ML signals, funding-rate skew, and natural-language market briefings.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "bpe-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE",
14
+ "SECURITY.md",
15
+ "SKILL.md"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "dev": "tsx src/index.ts",
23
+ "typecheck": "tsc --noEmit",
24
+ "prepare": "npm run build"
25
+ },
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.0.0",
28
+ "zod": "^3.23.8"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.0.0",
32
+ "tsx": "^4.19.0",
33
+ "typescript": "^5.6.0"
34
+ },
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "keywords": [
39
+ "mcp",
40
+ "model-context-protocol",
41
+ "bitcoin",
42
+ "market-data",
43
+ "bxetech",
44
+ "claude",
45
+ "ai-agents"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/bxetech/bpe-mcp.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/bxetech/bpe-mcp/issues"
53
+ },
54
+ "homepage": "https://bxetech.com/agents"
55
+ }