@cryptoquant_official/mcp 0.0.7 → 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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -307
  3. package/dist/auth/storage.d.ts.map +1 -0
  4. package/dist/auth/storage.js.map +1 -0
  5. package/dist/cache/storage.d.ts +47 -0
  6. package/dist/cache/storage.d.ts.map +1 -0
  7. package/dist/cache/storage.js +140 -0
  8. package/dist/cache/storage.js.map +1 -0
  9. package/dist/cache/summary.d.ts.map +1 -0
  10. package/dist/cache/summary.js.map +1 -0
  11. package/dist/{core/cache → cache}/types.d.ts +0 -25
  12. package/dist/{core/cache → cache}/types.d.ts.map +1 -1
  13. package/dist/cache/types.js.map +1 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/{core/config.js → config.js} +1 -1
  16. package/dist/config.js.map +1 -0
  17. package/dist/discovery.d.ts.map +1 -0
  18. package/dist/discovery.js.map +1 -0
  19. package/dist/index.d.ts +16 -8
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +28 -17
  22. package/dist/index.js.map +1 -1
  23. package/dist/{core/permissions.d.ts → permissions.d.ts} +1 -1
  24. package/dist/permissions.d.ts.map +1 -0
  25. package/dist/{core/permissions.js → permissions.js} +6 -6
  26. package/dist/permissions.js.map +1 -0
  27. package/dist/plan-limits.d.ts.map +1 -0
  28. package/dist/plan-limits.js.map +1 -0
  29. package/dist/tools/auth.d.ts.map +1 -0
  30. package/dist/{mcp/tools → tools}/auth.js +8 -10
  31. package/dist/tools/auth.js.map +1 -0
  32. package/dist/tools/core.d.ts.map +1 -0
  33. package/dist/{mcp/tools → tools}/core.js +145 -32
  34. package/dist/tools/core.js.map +1 -0
  35. package/dist/utils.d.ts.map +1 -0
  36. package/dist/utils.js.map +1 -0
  37. package/package.json +9 -45
  38. package/dist/ai-sdk/execute.d.ts +0 -35
  39. package/dist/ai-sdk/execute.d.ts.map +0 -1
  40. package/dist/ai-sdk/execute.js +0 -531
  41. package/dist/ai-sdk/execute.js.map +0 -1
  42. package/dist/ai-sdk/index.d.ts +0 -51
  43. package/dist/ai-sdk/index.d.ts.map +0 -1
  44. package/dist/ai-sdk/index.js +0 -54
  45. package/dist/ai-sdk/index.js.map +0 -1
  46. package/dist/ai-sdk/prompts.d.ts +0 -34
  47. package/dist/ai-sdk/prompts.d.ts.map +0 -1
  48. package/dist/ai-sdk/prompts.js +0 -74
  49. package/dist/ai-sdk/prompts.js.map +0 -1
  50. package/dist/ai-sdk/schemas.d.ts +0 -66
  51. package/dist/ai-sdk/schemas.d.ts.map +0 -1
  52. package/dist/ai-sdk/schemas.js +0 -136
  53. package/dist/ai-sdk/schemas.js.map +0 -1
  54. package/dist/ai-sdk/tools.d.ts +0 -165
  55. package/dist/ai-sdk/tools.d.ts.map +0 -1
  56. package/dist/ai-sdk/tools.js +0 -152
  57. package/dist/ai-sdk/tools.js.map +0 -1
  58. package/dist/ai-sdk/types.d.ts +0 -149
  59. package/dist/ai-sdk/types.d.ts.map +0 -1
  60. package/dist/ai-sdk/types.js +0 -5
  61. package/dist/ai-sdk/types.js.map +0 -1
  62. package/dist/core/auth/storage.d.ts.map +0 -1
  63. package/dist/core/auth/storage.js.map +0 -1
  64. package/dist/core/cache/storage.d.ts +0 -110
  65. package/dist/core/cache/storage.d.ts.map +0 -1
  66. package/dist/core/cache/storage.js +0 -356
  67. package/dist/core/cache/storage.js.map +0 -1
  68. package/dist/core/cache/summary.d.ts.map +0 -1
  69. package/dist/core/cache/summary.js.map +0 -1
  70. package/dist/core/cache/types.js.map +0 -1
  71. package/dist/core/config.d.ts.map +0 -1
  72. package/dist/core/config.js.map +0 -1
  73. package/dist/core/discovery.d.ts.map +0 -1
  74. package/dist/core/discovery.js.map +0 -1
  75. package/dist/core/index.d.ts +0 -16
  76. package/dist/core/index.d.ts.map +0 -1
  77. package/dist/core/index.js +0 -19
  78. package/dist/core/index.js.map +0 -1
  79. package/dist/core/permissions.d.ts.map +0 -1
  80. package/dist/core/permissions.js.map +0 -1
  81. package/dist/core/plan-limits.d.ts.map +0 -1
  82. package/dist/core/plan-limits.js.map +0 -1
  83. package/dist/core/utils.d.ts.map +0 -1
  84. package/dist/core/utils.js.map +0 -1
  85. package/dist/http/chat-proxy.d.ts +0 -32
  86. package/dist/http/chat-proxy.d.ts.map +0 -1
  87. package/dist/http/chat-proxy.js +0 -305
  88. package/dist/http/chat-proxy.js.map +0 -1
  89. package/dist/http/index.d.ts +0 -16
  90. package/dist/http/index.d.ts.map +0 -1
  91. package/dist/http/index.js +0 -26
  92. package/dist/http/index.js.map +0 -1
  93. package/dist/http/server.d.ts +0 -20
  94. package/dist/http/server.d.ts.map +0 -1
  95. package/dist/http/server.js +0 -204
  96. package/dist/http/server.js.map +0 -1
  97. package/dist/mcp/index.d.ts +0 -6
  98. package/dist/mcp/index.d.ts.map +0 -1
  99. package/dist/mcp/index.js +0 -6
  100. package/dist/mcp/index.js.map +0 -1
  101. package/dist/mcp/tools/auth.d.ts.map +0 -1
  102. package/dist/mcp/tools/auth.js.map +0 -1
  103. package/dist/mcp/tools/core.d.ts.map +0 -1
  104. package/dist/mcp/tools/core.js.map +0 -1
  105. package/dist/shared/metrics-data.generated.d.ts +0 -176
  106. package/dist/shared/metrics-data.generated.d.ts.map +0 -1
  107. package/dist/shared/metrics-data.generated.js +0 -3077
  108. package/dist/shared/metrics-data.generated.js.map +0 -1
  109. /package/dist/{core/auth → auth}/storage.d.ts +0 -0
  110. /package/dist/{core/auth → auth}/storage.js +0 -0
  111. /package/dist/{core/cache → cache}/summary.d.ts +0 -0
  112. /package/dist/{core/cache → cache}/summary.js +0 -0
  113. /package/dist/{core/cache → cache}/types.js +0 -0
  114. /package/dist/{core/config.d.ts → config.d.ts} +0 -0
  115. /package/dist/{core/discovery.d.ts → discovery.d.ts} +0 -0
  116. /package/dist/{core/discovery.js → discovery.js} +0 -0
  117. /package/dist/{core/plan-limits.d.ts → plan-limits.d.ts} +0 -0
  118. /package/dist/{core/plan-limits.js → plan-limits.js} +0 -0
  119. /package/dist/{mcp/tools → tools}/auth.d.ts +0 -0
  120. /package/dist/{mcp/tools → tools}/core.d.ts +0 -0
  121. /package/dist/{core/utils.d.ts → utils.d.ts} +0 -0
  122. /package/dist/{core/utils.js → utils.js} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CryptoQuant
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 CHANGED
@@ -1,381 +1,183 @@
1
- # @cryptoquant_official/mcp
1
+ # CryptoQuant MCP Server
2
2
 
3
- CryptoQuant on-chain analytics for Claude and AI applications.
3
+ <p align="center">
4
+ <strong>On-Chain Analytics for Claude and AI Coding Agents</strong>
5
+ </p>
4
6
 
5
- ## Integration Modes
7
+ <p align="center">
8
+ <a href="#installation">Installation</a> •
9
+ <a href="#mcp-tools">MCP Tools</a> •
10
+ <a href="#authentication">Authentication</a>
11
+ </p>
6
12
 
7
- | Mode | Use Case | Streaming | Setup |
8
- |------|----------|-----------|-------|
9
- | [**MCP**](#mode-1-mcp-claude-desktopcode) | Claude Desktop, Claude Code, Cursor | - | Config file |
10
- | [**AI SDK**](#mode-2-ai-sdk-nextjs) | Next.js web apps | ✅ | npm package |
11
- | [**HTTP**](#mode-3-http-chat-proxy) | Any backend / non-Node.js | ❌ | Standalone server |
13
+ ---
14
+
15
+ ## What is this?
12
16
 
13
- **Get your API key**: [cryptoquant.com/settings/api](https://cryptoquant.com/settings/api)
17
+ CryptoQuant MCP Server brings on-chain analytics directly into your AI assistant:
18
+
19
+ - **Natural language queries**: Ask in any language - "비트코인 가격 전망?" or "Is BTC overvalued?"
20
+ - **Real-time metrics**: MVRV, SOPR, Exchange Flows, Funding Rates
21
+ - **Market insights**: AI-powered interpretation of on-chain data
22
+ - **Whale tracking**: Monitor large holder movements
14
23
 
15
24
  ---
16
25
 
17
- ## Mode 1: MCP (Claude Desktop/Code)
26
+ ## Installation
18
27
 
19
- For Claude Desktop, Claude Code, Cursor, and other MCP-compatible apps.
28
+ ### Quick Start (Claude Desktop, Cursor, etc.)
20
29
 
21
- ### Setup
30
+ **Step 1**: Add to your MCP config file:
22
31
 
23
- **Claude Code** (`~/.claude/mcp.json` or `.mcp.json`):
24
- ```json
25
- {
26
- "mcpServers": {
27
- "cryptoquant": {
28
- "command": "npx",
29
- "args": ["-y", "@cryptoquant_official/mcp"],
30
- "env": {
31
- "CRYPTOQUANT_API_KEY": "your-api-key"
32
- }
33
- }
34
- }
35
- }
36
- ```
32
+ | App | Config File |
33
+ |-----|-------------|
34
+ | **Claude Desktop (Mac)** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
35
+ | **Claude Desktop (Windows)** | `%APPDATA%\Claude\claude_desktop_config.json` |
36
+ | **Claude Code** | `~/.claude/mcp.json` or project `.mcp.json` |
37
+ | **Cursor** | Project `.cursor/mcp.json` |
37
38
 
38
- **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
39
39
  ```json
40
40
  {
41
41
  "mcpServers": {
42
42
  "cryptoquant": {
43
43
  "command": "npx",
44
- "args": ["-y", "@cryptoquant_official/mcp"],
45
- "env": {
46
- "CRYPTOQUANT_API_KEY": "your-api-key"
47
- }
44
+ "args": ["-y", "@cryptoquant_official/mcp"]
48
45
  }
49
46
  }
50
47
  }
51
48
  ```
52
49
 
53
- Restart your app after configuration.
54
-
55
- ### Usage
56
-
57
- ```
58
- User: "Is Bitcoin overvalued?"
59
-
60
- Claude: Let me check the MVRV ratio...
61
- → Calls query_data({ endpoint: "/v1/btc/market-data/mvrv" })
62
- → Returns analysis with current valuation status
63
- ```
64
-
65
- ---
50
+ **Step 2**: Restart your app
66
51
 
67
- ## Mode 2: AI SDK (Next.js)
52
+ **Step 3**: Call `initialize()` to verify connection. Done!
68
53
 
69
- For Next.js web apps with streaming responses via Vercel AI SDK.
54
+ ### Local Development
70
55
 
71
- ### Installation
56
+ For contributors:
72
57
 
73
58
  ```bash
74
- npm install @cryptoquant_official/mcp ai @ai-sdk/react @ai-sdk/anthropic
59
+ git clone https://github.com/CryptoQuantOfficial/mcp.git
60
+ cd mcp
61
+ npm install && npm run build
75
62
  ```
76
63
 
77
- ### Environment Variables
78
-
79
- ```env
80
- # .env.local
81
- ANTHROPIC_API_KEY=sk-ant-...
82
- CRYPTOQUANT_API_KEY=cq-...
83
- ```
84
-
85
- > `@ai-sdk/anthropic` automatically reads `ANTHROPIC_API_KEY`.
86
-
87
- ### API Route
88
-
89
- ```typescript
90
- // app/api/chat/route.ts
91
- import { streamText } from "ai";
92
- import { anthropic } from "@ai-sdk/anthropic";
93
- import { createCryptoQuantTools } from "@cryptoquant_official/mcp/ai-sdk";
94
-
95
- export const maxDuration = 60;
96
-
97
- export async function POST(req: Request) {
98
- const { messages } = await req.json();
99
-
100
- const result = streamText({
101
- model: anthropic("claude-sonnet-4-20250514"),
102
- messages,
103
- tools: createCryptoQuantTools({
104
- cryptoquantApiKey: process.env.CRYPTOQUANT_API_KEY!,
105
- }),
106
- maxSteps: 5,
107
- });
108
-
109
- return result.toDataStreamResponse();
110
- }
111
- ```
64
+ ---
112
65
 
113
- ### Client Component
114
-
115
- ```tsx
116
- "use client";
117
- import { useChat } from "@ai-sdk/react";
118
-
119
- export function CryptoChat() {
120
- const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
121
-
122
- return (
123
- <div>
124
- {messages.map((m) => (
125
- <div key={m.id}>{m.content}</div>
126
- ))}
127
- <form onSubmit={handleSubmit}>
128
- <input value={input} onChange={handleInputChange} />
129
- <button type="submit" disabled={isLoading}>Send</button>
130
- </form>
131
- </div>
132
- );
133
- }
134
- ```
66
+ ## MCP Tools
135
67
 
136
- ### API Reference
68
+ The MCP server provides these tools for API access:
137
69
 
138
- ```typescript
139
- // Option 1: With explicit API key
140
- import { createCryptoQuantTools } from "@cryptoquant_official/mcp/ai-sdk";
141
- const tools = createCryptoQuantTools({ cryptoquantApiKey: "cq-..." });
70
+ | Tool | Description |
71
+ |------|-------------|
72
+ | `initialize` | Start session with API key, returns plan info |
73
+ | `discover_endpoints` | Browse 245+ available endpoints |
74
+ | `get_endpoint_info` | Get endpoint parameter details |
75
+ | `query_data` | Query raw API data |
76
+ | `describe_metric` | Get metric descriptions and thresholds |
77
+ | `list_assets` | List supported assets |
78
+ | `reset_session` | Clear session (logout) |
142
79
 
143
- // Option 2: Using CRYPTOQUANT_API_KEY env var
144
- import { cryptoQuantTools } from "@cryptoquant_official/mcp/ai-sdk";
145
- streamText({ tools: cryptoQuantTools, ... });
146
- ```
80
+ ### Supported Assets
147
81
 
148
- See [examples/nextjs-ai-sdk/](examples/nextjs-ai-sdk/) for complete example.
82
+ BTC, ETH, ALT, Stablecoin, ERC20, TRX, XRP
149
83
 
150
84
  ---
151
85
 
152
- ## Mode 3: HTTP (Chat Proxy)
153
-
154
- Standalone HTTP server for any backend or non-Node.js environments.
86
+ ## Natural Language Queries
155
87
 
156
- ### Start Server
88
+ Ask questions in any language - Claude will route to the right metrics:
157
89
 
158
- ```bash
159
- MCP_TRANSPORT=http npx @cryptoquant_official/mcp
160
- # Server runs at http://localhost:3100
161
- ```
90
+ | Query | Intent | Metric |
91
+ |-------|--------|--------|
92
+ | "비트코인 가격 전망이 어때?" | VALUATION | MVRV |
93
+ | "Is BTC overvalued?" | VALUATION | MVRV |
94
+ | "고래들 움직임 보여줘" | WHALE_ACTIVITY | whale-ratio |
95
+ | "What's the funding rate?" | LEVERAGE | funding-rates |
96
+ | "익절/손절 상황?" | PROFIT_BEHAVIOR | SOPR |
162
97
 
163
- ### Endpoints
164
-
165
- | Endpoint | Method | Description |
166
- |----------|--------|-------------|
167
- | `/chat` | POST | Chat with Claude + automatic tool execution |
168
- | `/tools/schema` | GET | Get Claude API tool definitions |
169
- | `/health` | GET | Server health check |
170
- | `/mcp` | POST/GET/DELETE | Streamable HTTP MCP protocol |
98
+ ---
171
99
 
172
- ### POST /chat
100
+ ## Authentication
173
101
 
174
- ```bash
175
- curl -X POST http://localhost:3100/chat \
176
- -H "Content-Type: application/json" \
177
- -d '{
178
- "message": "Analyze Bitcoin MVRV",
179
- "claude_api_key": "sk-ant-...",
180
- "cryptoquant_api_key": "cq-..."
181
- }'
182
- ```
102
+ ### Option A. Environment Variable (Recommended)
183
103
 
184
- **Request:**
185
- ```json
186
- {
187
- "message": "Is Bitcoin overvalued?",
188
- "claude_api_key": "sk-ant-...",
189
- "cryptoquant_api_key": "cq-...",
190
- "conversation_id": "optional-session-id",
191
- "model": "claude-sonnet-4-20250514"
192
- }
193
- ```
104
+ Add your API key to the MCP config:
194
105
 
195
- **Response:**
196
106
  ```json
197
107
  {
198
- "success": true,
199
- "response": "Based on the current MVRV of 2.1...",
200
- "tool_calls": [
201
- { "name": "initialize", "result": { "success": true } },
202
- { "name": "query_data", "result": { "data": [...] } }
203
- ],
204
- "conversation_id": "abc-123",
205
- "usage": { "input_tokens": 150, "output_tokens": 300 }
206
- }
207
- ```
208
-
209
- ### Next.js with HTTP Mode
210
-
211
- ```typescript
212
- // app/api/chat/route.ts
213
- export async function POST(request: Request) {
214
- const { message, conversation_id } = await request.json();
215
-
216
- const response = await fetch("http://localhost:3100/chat", {
217
- method: "POST",
218
- headers: { "Content-Type": "application/json" },
219
- body: JSON.stringify({
220
- message,
221
- claude_api_key: process.env.CLAUDE_API_KEY,
222
- cryptoquant_api_key: process.env.CRYPTOQUANT_API_KEY,
223
- conversation_id,
224
- }),
225
- });
226
-
227
- return Response.json(await response.json());
228
- }
229
- ```
230
-
231
- See [examples/nextjs/](examples/nextjs/) for complete example.
232
-
233
- ---
234
-
235
- ## Custom Cache Storage
236
-
237
- The MCP server caches API discovery data to reduce startup time. By default:
238
- - **CLI/Local**: File storage (`~/.cryptoquant/discovery-cache.json`)
239
- - **Web Server**: No caching (requires Redis configuration)
240
-
241
- ### Redis Storage for Web Servers
242
-
243
- For production web servers or serverless environments, configure Redis storage:
244
-
245
- ```typescript
246
- // app/lib/cryptoquant-cache.ts
247
- import { createClient } from "redis";
248
- import { setRedisStorage, type CacheStorage } from "@cryptoquant_official/mcp";
249
-
250
- const redis = createClient({ url: process.env.REDIS_URL });
251
-
252
- export async function configureRedisCache() {
253
- if (!redis.isOpen) {
254
- await redis.connect();
255
- }
256
-
257
- const redisStorage: CacheStorage = {
258
- type: "redis",
259
-
260
- async read(apiUrl, apiKeyPrefix) {
261
- const key = `cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`;
262
- const data = await redis.get(key);
263
- return data ? JSON.parse(data) : null;
264
- },
265
-
266
- async write(apiUrl, cache) {
267
- const key = `cryptoquant:cache:${apiUrl}:${cache.metadata.api_key_prefix}`;
268
- const ttl = 7 * 24 * 60 * 60; // 7 days
269
- await redis.setEx(key, ttl, JSON.stringify(cache));
270
- },
271
-
272
- async invalidate(apiUrl, apiKeyPrefix) {
273
- if (apiKeyPrefix) {
274
- await redis.del(`cryptoquant:cache:${apiUrl}:${apiKeyPrefix}`);
275
- } else {
276
- const keys = await redis.keys(`cryptoquant:cache:${apiUrl}:*`);
277
- if (keys.length > 0) await redis.del(keys);
108
+ "mcpServers": {
109
+ "cryptoquant": {
110
+ "command": "npx",
111
+ "args": ["-y", "@cryptoquant_official/mcp"],
112
+ "env": {
113
+ "CRYPTOQUANT_API_KEY": "your-api-key"
278
114
  }
279
- },
280
-
281
- async clearAll() {
282
- const keys = await redis.keys("cryptoquant:cache:*");
283
- if (keys.length > 0) await redis.del(keys);
284
- },
285
-
286
- getPath() {
287
- return "[redis]";
288
- },
289
- };
290
-
291
- setRedisStorage(redisStorage);
115
+ }
116
+ }
292
117
  }
293
118
  ```
294
119
 
295
- ```typescript
296
- // app/api/chat/route.ts
297
- import { configureRedisCache } from "@/lib/cryptoquant-cache";
120
+ ### Option B. Direct Parameter
298
121
 
299
- // Configure once at startup
300
- await configureRedisCache();
122
+ Call `initialize()` with your API key:
301
123
 
302
- export async function POST(req: Request) {
303
- // ... your chat handler
304
- }
124
+ ```
125
+ initialize(api_key="your-api-key")
305
126
  ```
306
127
 
307
- ### CacheStorage Interface
308
-
309
- Implement this interface for custom storage backends:
310
-
311
- ```typescript
312
- interface CacheStorage {
313
- /** Storage type identifier */
314
- readonly type: "file" | "redis" | "auto";
128
+ The key will be saved to `~/.cryptoquant/credentials` for future sessions.
315
129
 
316
- /** Read cache data, returns null if not found */
317
- read(apiUrl: string, apiKeyPrefix?: string): Promise<DiscoveryCacheSchema | null> | DiscoveryCacheSchema | null;
130
+ **Get your API key**: [https://cryptoquant.com/settings/api](https://cryptoquant.com/settings/api)
318
131
 
319
- /** Write cache data */
320
- write(apiUrl: string, cache: DiscoveryCacheSchema): Promise<void> | void;
132
+ ### Managing Credentials
321
133
 
322
- /** Delete cache for specific API URL */
323
- invalidate(apiUrl: string, apiKeyPrefix?: string): Promise<void> | void;
134
+ ```bash
135
+ # Switch accounts
136
+ reset_session(clear_stored=true)
137
+ initialize(api_key="new-api-key")
138
+ ```
324
139
 
325
- /** Clear all caches */
326
- clearAll(): Promise<void> | void;
140
+ ---
327
141
 
328
- /** Get storage path for display */
329
- getPath(apiUrl: string): string;
330
- }
331
- ```
142
+ ## Requirements
332
143
 
333
- See [examples/redis-cache/](examples/redis-cache/) for complete implementation.
144
+ | Component | Requirement |
145
+ |-----------|-------------|
146
+ | Node.js | v18+ |
147
+ | API Access | [CryptoQuant API key](https://cryptoquant.com/settings/api) |
334
148
 
335
149
  ---
336
150
 
337
- ## Reference
151
+ ## License
338
152
 
339
- ### Available Tools
153
+ MIT License - see [LICENSE](LICENSE)
340
154
 
341
- | Tool | Description |
342
- |------|-------------|
343
- | `initialize` | Start session with API key |
344
- | `discover_endpoints` | Browse 245+ available API endpoints |
345
- | `get_endpoint_info` | Get endpoint parameter details |
346
- | `query_data` | Query raw on-chain data |
347
- | `describe_metric` | Get metric descriptions and thresholds |
348
- | `list_assets` | List supported assets |
349
- | `reset_session` | Clear session / switch accounts |
155
+ ---
350
156
 
351
- ### Supported Assets
157
+ ## Development
352
158
 
353
- BTC, ETH, ALT, Stablecoin, ERC20, TRX, XRP
159
+ ### Setup
354
160
 
355
- ### Environment Variables
161
+ After cloning the repository, install dependencies to set up git hooks:
356
162
 
357
- | Variable | Description | Default |
358
- |----------|-------------|---------|
359
- | `CRYPTOQUANT_API_KEY` | CryptoQuant API key | - |
360
- | `ANTHROPIC_API_KEY` | Anthropic API key (AI SDK mode) | - |
361
- | `MCP_TRANSPORT` | Transport mode (`stdio` / `http`) | `stdio` |
362
- | `MCP_HTTP_PORT` | HTTP server port | `3100` |
363
- | `MCP_HTTP_HOST` | HTTP server host | `0.0.0.0` |
364
- | `MCP_CORS_ORIGINS` | CORS allowed origins | `*` |
365
- | `DEBUG` | Enable debug logging | - |
163
+ ```bash
164
+ npm install
165
+ ```
366
166
 
367
- ### Requirements
167
+ This automatically configures [husky](https://typicode.github.io/husky/) for pre-commit hooks.
368
168
 
369
- - Node.js 18+
370
- - CryptoQuant API key
371
- - Anthropic API key (for AI SDK / HTTP mode)
169
+ ### Pre-commit Hooks
372
170
 
373
- ## Links
171
+ When committing changes to `src/`, ESLint runs automatically:
374
172
 
375
- - [GitHub](https://github.com/CryptoQuantOfficial/cryptoquant-skills)
376
- - [CryptoQuant](https://cryptoquant.com)
377
- - [API Docs](https://docs.cryptoquant.com)
173
+ - Lint check runs only when files in `src/` are staged
174
+ - Commit is blocked if lint errors are found
175
+ - Fix errors before committing: `npm run lint`
378
176
 
379
- ## License
177
+ ---
380
178
 
381
- MIT
179
+ <p align="center">
180
+ <a href="https://cryptoquant.com">CryptoQuant</a> •
181
+ <a href="https://docs.cryptoquant.com">Docs</a> •
182
+ <a href="https://github.com/CryptoQuantOfficial/mcp/issues">Issues</a>
183
+ </p>
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAQ/C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAa/C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CASxC;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/F,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAQ9D,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACjC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAsB;QAC9B,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACvC,CAAC;IAEF,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACtF,SAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,OAAO;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAsB,CAAC;QACtF,IAAI,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,aAAa,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,gBAAgB,CAAC;YAAE,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Cache storage operations for discovery response caching
3
+ */
4
+ import { type DiscoveryCacheSchema, type MyDiscoveryRawResponse, type DiscoverySummaryData } from "./types.js";
5
+ import type { UserPlan, PlanLimits, ApiRateLimit } from "../plan-limits.js";
6
+ /**
7
+ * Get cache file path.
8
+ */
9
+ export declare function getCacheFilePath(_apiUrl: string): string;
10
+ /**
11
+ * Check if cache is still valid (not expired and version matches).
12
+ */
13
+ export declare function isCacheValid(cache: DiscoveryCacheSchema, apiUrl: string, apiKeyPrefix: string): boolean;
14
+ /**
15
+ * Read cache from file.
16
+ * Returns null if cache doesn't exist or is invalid JSON.
17
+ */
18
+ export declare function readCache(apiUrl: string): DiscoveryCacheSchema | null;
19
+ /**
20
+ * Write cache to file with secure permissions.
21
+ */
22
+ export declare function writeCache(apiUrl: string, apiKey: string, rawResponse: MyDiscoveryRawResponse, parsed: {
23
+ limits: PlanLimits | null;
24
+ statics: string[];
25
+ apiRateLimit: ApiRateLimit | null;
26
+ }, summary: DiscoverySummaryData, plan: UserPlan): void;
27
+ /**
28
+ * Delete cache file.
29
+ */
30
+ export declare function invalidateCache(apiUrl: string): void;
31
+ /**
32
+ * Delete the cache file.
33
+ */
34
+ export declare function clearAllCaches(): void;
35
+ /**
36
+ * Calculate cache age in days.
37
+ */
38
+ export declare function getCacheAgeDays(cache: DiscoveryCacheSchema): number;
39
+ /**
40
+ * Get human-readable cache status string.
41
+ */
42
+ export declare function getCacheStatus(cache: DiscoveryCacheSchema | null, fromCache: boolean): string;
43
+ /**
44
+ * Get cache file path for user display.
45
+ */
46
+ export declare function getCachePath(): string;
47
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/cache/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAG1B,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAK5E;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAuBvG;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAmBrE;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,sBAAsB,EACnC,MAAM,EAAE;IACN,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC,EACD,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,QAAQ,GACb,IAAI,CA2BN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAUpD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAQrC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAKnE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAM7F;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}