@sharpe-terminal/mcp-server 1.2.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,193 @@
1
+ # @sharpe-terminal/mcp-server
2
+
3
+ Model Context Protocol (MCP) server for the Sharpe crypto derivatives and market data API. Enables AI agents (Claude, Cursor, Windsurf, etc.) to query real-time crypto market data including funding rates, futures, arbitrage opportunities, narratives, ecosystems, and more.
4
+
5
+ ## Installation
6
+
7
+ Requires Node.js 18 or later.
8
+
9
+ ### npx (no install)
10
+
11
+ ```bash
12
+ npx @sharpe-terminal/mcp-server
13
+ ```
14
+
15
+ ### Global install
16
+
17
+ ```bash
18
+ npm install -g @sharpe-terminal/mcp-server
19
+ sharpe-mcp
20
+ ```
21
+
22
+ ## Configuration
23
+
24
+ ### Environment Variables
25
+
26
+ | Variable | Required | Default | Description |
27
+ |---|---|---|---|
28
+ | `SHARPE_API_KEY` | No | — | Your Sharpe API key (`sk_live_...`). When set, uses the authenticated `/api/v1/` endpoints with higher rate limits. |
29
+ | `SHARPE_API_URL` | No | `https://www.sharpe.ai` | Base URL for authenticated `/api/v1/*` API requests. |
30
+ | `SHARPE_FREE_URL` | No | `https://www.sharpe.ai` | Base URL for free `/api/*` fallback requests. |
31
+
32
+ Without an API key, the server falls back to free public endpoints when a matching public route exists. Authenticated-only `/api/v1/*` tools require `SHARPE_API_KEY`.
33
+
34
+ Custom base URLs must use `https://`, except `http://localhost`/`127.0.0.1`/`::1` for local development. The server refuses API redirects so credentials are not forwarded to unexpected hosts.
35
+
36
+ ### Claude Desktop
37
+
38
+ Add to your `claude_desktop_config.json` (usually at `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "sharpe": {
44
+ "command": "npx",
45
+ "args": ["-y", "@sharpe-terminal/mcp-server"],
46
+ "env": {
47
+ "SHARPE_API_KEY": "sk_live_your_key_here"
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Claude Code
55
+
56
+ ```bash
57
+ claude mcp add sharpe -- npx -y @sharpe-terminal/mcp-server
58
+ ```
59
+
60
+ Or with an API key:
61
+
62
+ ```bash
63
+ SHARPE_API_KEY=sk_live_your_key_here claude mcp add sharpe -- npx -y @sharpe-terminal/mcp-server
64
+ ```
65
+
66
+ ### Cursor
67
+
68
+ Add to your `.cursor/mcp.json`:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "sharpe": {
74
+ "command": "npx",
75
+ "args": ["-y", "@sharpe-terminal/mcp-server"],
76
+ "env": {
77
+ "SHARPE_API_KEY": "sk_live_your_key_here"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Local development (from source)
85
+
86
+ ```bash
87
+ cd packages/mcp-server
88
+ npm install
89
+ npm run build
90
+ node dist/index.js
91
+ ```
92
+
93
+ ## Available Tools
94
+
95
+ The TypeScript package exposes 41 tools: 38 endpoint tools plus 3 composite workflows (`analyze_coin`, `market_briefing`, `find_opportunities`). The Python `sharpe-terminal-mcp` package mirrors this surface and is the primary distribution for the companion CLI.
96
+
97
+ All tools are read-only market-data calls. They advertise MCP annotations for `readOnlyHint`, `destructiveHint=false`, `idempotentHint`, and `openWorldHint`. Endpoint tools return both `structuredContent` (`{ "result": ... }`) and text JSON for older clients. Composite workflow tools return `{ "report": "..." }` in `structuredContent` plus the same markdown report in text content.
98
+
99
+ Large list responses are capped at 200 rows before they are returned to the MCP client. Truncated payloads include `truncated`, `total`, and `showing` fields.
100
+
101
+ Release checklist and cross-package synchronization notes live in [`../../docs/release-packages.md`](../../docs/release-packages.md).
102
+
103
+ ### Composite Workflows
104
+
105
+ | Tool | Description |
106
+ |---|---|
107
+ | `analyze_coin` | Single-coin analysis combining funding, futures OI, and prediction data |
108
+ | `market_briefing` | Market overview, narrative leaders, and funding highlights in one briefing |
109
+ | `find_opportunities` | Funding-rate and arbitrage opportunity scan across multiple sources |
110
+
111
+ ### Derivatives
112
+
113
+ | Tool | Description |
114
+ |---|---|
115
+ | `get_funding_rates` | Perpetual funding rates across exchanges (current, accumulated, or historical) |
116
+ | `get_futures_data` | Futures chart data: OI, volume, liquidations, long/short ratios, basis, term structure |
117
+ | `get_futures_coins` | List of coins with futures data and exchange capability flags |
118
+ | `get_derivatives_overview` | Market-wide derivatives snapshot: total OI, weighted funding, top coins, and exchange counts |
119
+
120
+ ### Market Data
121
+
122
+ | Tool | Description |
123
+ |---|---|
124
+ | `get_heatmap` | Market heatmap by coins, narratives, or ecosystems |
125
+ | `get_correlation_matrix` | Price correlation matrix for portfolio analysis |
126
+ | `get_market_overview` | Total market cap, BTC dominance, top gainers/losers, trending coins |
127
+ | `get_price_prediction` | ML-based price predictions with confidence intervals |
128
+ | `search_market_cap` | Search coins by name or ticker with market cap data |
129
+ | `get_news` | Aggregated crypto news with category and coin filters |
130
+ | `get_curated_news` | Curated crypto news highlights |
131
+ | `get_gem_finder` | Curated low-cap, high-potential token discovery |
132
+ | `get_stablecoins` | Stablecoin overview, detail, peg, chain supply, and yield data |
133
+ | `get_mindshare` | Narrative mindshare, token-level attention, and historical snapshots |
134
+ | `get_web_traffic` | Attention rankings, search trends, and social/developer snapshots |
135
+ | `get_katana` | Katana Network TVL, token, holder, sentiment, pool, and ecosystem analytics |
136
+
137
+ ### Screener
138
+
139
+ | Tool | Description |
140
+ |---|---|
141
+ | `get_dexscreener_data` | Live DEX pair screening by category, network, or search phrase |
142
+ | `get_dexscreener_security` | Token contract security signals for DEX Screener tokens |
143
+ | `get_token_scanner` | Read-only hot token, new runner, alpha drop, AI token, and top-new scans |
144
+ | `get_rug_check_security` | Token contract and liquidity risk signals |
145
+ | `get_rug_check_trending` | Trending tokens suitable for rug-check review |
146
+ | `get_insider_selling` | Insider selling pressure and holder-quality risk signals |
147
+ | `get_pump_dump` | Pump-and-dump manipulation risk signals |
148
+
149
+ ### Arbitrage
150
+
151
+ | Tool | Description |
152
+ |---|---|
153
+ | `get_arbitrage_spot_perp` | Spot-perpetual funding rate arbitrage opportunities |
154
+ | `get_arbitrage_cross_exchange` | Cross-exchange price discrepancy arbitrage |
155
+ | `get_arbitrage_dated_futures_basis` | Spot-futures cash-and-carry basis rows |
156
+ | `get_arbitrage_futures_calendar_spread` | Near-versus-far dated futures curve rows |
157
+ | `get_arbitrage_perp_dated_carry` | Perp funding versus dated futures carry rows |
158
+ | `get_arbitrage_cex_spot_transfer` | CEX spot-transfer rows with network, fee, depth, and slippage checks |
159
+
160
+ ### Categories
161
+
162
+ | Tool | Description |
163
+ |---|---|
164
+ | `get_narratives` | Narrative-level data: L1, L2, DeFi, AI Agents, DePIN, RWA, etc. |
165
+ | `get_ecosystems` | Ecosystem-level data: Ethereum, Solana, Arbitrum, Base, etc. with TVL |
166
+ | `get_memecoins` | Memecoin narrative data: Dog, Cat, Frog, AI, Solana, Base, Pump.fun, etc. |
167
+ | `get_memecoin_launches` | Recently launched memecoin pairs screened by age, liquidity, volume, and transactions |
168
+ | `get_exchange_listings` | New Listings aggregate activity by narrative and venue |
169
+ | `get_recent_listings` | Recent token listings feed |
170
+ | `get_listing_events` | Canonical listing lifecycle events with source confidence |
171
+ | `get_listing_exchanges` | Listing connector coverage and parser status |
172
+
173
+ ### System
174
+
175
+ | Tool | Description |
176
+ |---|---|
177
+ | `get_api_coverage` | Available data products, exchanges, timeframes, and chart coverage |
178
+
179
+ ## Example Prompts
180
+
181
+ Once connected, you can ask your AI agent things like:
182
+
183
+ - "What are the current BTC funding rates across exchanges?"
184
+ - "Show me the top spot-perp arbitrage opportunities"
185
+ - "What's the correlation between BTC, ETH, and SOL over the last 90 days?"
186
+ - "Show me the DeFi narrative performance data"
187
+ - "Search for Solana in the market cap tracker"
188
+ - "What are the latest crypto news about Bitcoin?"
189
+ - "Get the futures open interest chart for ETH over the last month"
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,13 @@
1
+ export type ApiCaller = (apiPath: string, fallbackPath: string, args: Record<string, unknown>) => Promise<unknown>;
2
+ export interface ApiClientOptions {
3
+ apiKey?: string;
4
+ apiBaseUrl: string;
5
+ fallbackBaseUrl: string;
6
+ userAgent: string;
7
+ fetchImpl?: typeof fetch;
8
+ }
9
+ export declare function normalizeBaseUrl(base: string): string;
10
+ export declare function redactUrl(input: string): string;
11
+ export declare function buildUrl(base: string, path: string, params: Record<string, unknown>): string;
12
+ export declare function createApiCaller(options: ApiClientOptions): ApiCaller;
13
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,CACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsCrD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS/C;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAQR;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAgEpE"}
@@ -0,0 +1,105 @@
1
+ const LOCAL_HTTP_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
2
+ export function normalizeBaseUrl(base) {
3
+ const normalized = base.trim().replace(/\/+$/, "");
4
+ if (!normalized)
5
+ throw new Error("Base URL must not be empty");
6
+ let url;
7
+ try {
8
+ url = new URL(normalized);
9
+ }
10
+ catch {
11
+ throw new Error("Base URL must be an absolute http(s) URL");
12
+ }
13
+ if (!["https:", "http:"].includes(url.protocol) || !url.host) {
14
+ throw new Error("Base URL must be an absolute http(s) URL");
15
+ }
16
+ if (url.username || url.password) {
17
+ throw new Error("Base URL must not contain credentials");
18
+ }
19
+ if (url.search || url.hash) {
20
+ throw new Error("Base URL must not contain query strings or fragments");
21
+ }
22
+ if (url.protocol === "http:" && !LOCAL_HTTP_HOSTS.has(url.hostname)) {
23
+ throw new Error("Refusing insecure SHARPE_API_URL/SHARPE_FREE_URL; use https:// or http://localhost for local development");
24
+ }
25
+ let path = url.pathname.replace(/\/+$/, "");
26
+ for (const suffix of ["/api/v1", "/api"]) {
27
+ if (path.endsWith(suffix)) {
28
+ path = path.slice(0, -suffix.length);
29
+ break;
30
+ }
31
+ }
32
+ url.pathname = path || "/";
33
+ url.search = "";
34
+ url.hash = "";
35
+ return url.toString().replace(/\/$/, "");
36
+ }
37
+ export function redactUrl(input) {
38
+ try {
39
+ const url = new URL(input);
40
+ url.search = "";
41
+ url.hash = "";
42
+ return url.toString();
43
+ }
44
+ catch {
45
+ return input;
46
+ }
47
+ }
48
+ export function buildUrl(base, path, params) {
49
+ const url = new URL(path, base);
50
+ for (const [key, value] of Object.entries(params)) {
51
+ if (value !== undefined && value !== null && value !== "") {
52
+ url.searchParams.set(key, String(value));
53
+ }
54
+ }
55
+ return url.toString();
56
+ }
57
+ export function createApiCaller(options) {
58
+ const apiKey = (options.apiKey ?? "").trim();
59
+ const apiBaseUrl = normalizeBaseUrl(options.apiBaseUrl);
60
+ const fallbackBaseUrl = normalizeBaseUrl(options.fallbackBaseUrl);
61
+ const fetchImpl = options.fetchImpl ?? fetch;
62
+ return async function callApi(apiPath, fallbackPath, args) {
63
+ const useAuthenticatedApi = apiKey.length > 0;
64
+ const base = useAuthenticatedApi ? apiBaseUrl : fallbackBaseUrl;
65
+ const path = useAuthenticatedApi ? apiPath : fallbackPath;
66
+ const url = buildUrl(base, path, args);
67
+ const headers = {
68
+ Accept: "application/json",
69
+ "User-Agent": options.userAgent,
70
+ };
71
+ if (useAuthenticatedApi) {
72
+ headers.Authorization = `Bearer ${apiKey}`;
73
+ }
74
+ const response = await fetchImpl(url, {
75
+ method: "GET",
76
+ headers,
77
+ redirect: "manual",
78
+ signal: AbortSignal.timeout(30_000),
79
+ });
80
+ if (response.status >= 300 && response.status < 400) {
81
+ const location = response.headers.get("location") ?? "unknown";
82
+ throw new Error(`Sharpe API redirected ${redactUrl(url)} to ${location}. Refusing to follow redirects to protect credentials; set SHARPE_API_URL/SHARPE_FREE_URL to the canonical HTTPS host.`);
83
+ }
84
+ if (!response.ok) {
85
+ const body = await response.text().catch(() => "");
86
+ throw new Error(`API returned ${response.status} ${response.statusText}: ${body.slice(0, 500)}`);
87
+ }
88
+ let data;
89
+ try {
90
+ data = await response.json();
91
+ }
92
+ catch {
93
+ throw new Error(`API returned invalid JSON for ${apiPath}`);
94
+ }
95
+ if (data &&
96
+ typeof data === "object" &&
97
+ !Array.isArray(data) &&
98
+ "data" in data &&
99
+ "meta" in data) {
100
+ return data.data;
101
+ }
102
+ return data;
103
+ };
104
+ }
105
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Composite tools that call multiple API endpoints concurrently
3
+ * and return formatted markdown. Mirrors the Python server's
4
+ * analyze_coin, market_briefing, and find_opportunities.
5
+ */
6
+ export declare function fmtUsd(value: number | null | undefined): string;
7
+ export declare function fmtPct(value: number | null | undefined): string;
8
+ export declare function fmtRate(value: number | null | undefined): string;
9
+ type ApiCaller = (apiPath: string, fallbackPath: string, args: Record<string, unknown>) => Promise<unknown>;
10
+ export declare function analyzeCoin(callApi: ApiCaller, coin: string): Promise<string>;
11
+ export declare function marketBriefing(callApi: ApiCaller): Promise<string>;
12
+ export declare function findOpportunities(callApi: ApiCaller): Promise<string>;
13
+ export {};
14
+ //# sourceMappingURL=composite-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite-tools.d.ts","sourceRoot":"","sources":["../src/composite-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAW/D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAG/D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGhE;AAgBD,KAAK,SAAS,GAAG,CACf,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AAuCtB,wBAAsB,WAAW,CAC/B,OAAO,EAAE,SAAS,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAgNjB;AAID,wBAAsB,cAAc,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CA6LxE;AAID,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAiM3E"}