cryptoquant-mcp 0.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/LICENSE +21 -0
- package/README.md +183 -0
- package/dist/auth/storage.d.ts +11 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +53 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/cache/storage.d.ts +47 -0
- package/dist/cache/storage.d.ts.map +1 -0
- package/dist/cache/storage.js +140 -0
- package/dist/cache/storage.js.map +1 -0
- package/dist/cache/summary.d.ts +16 -0
- package/dist/cache/summary.d.ts.map +1 -0
- package/dist/cache/summary.js +85 -0
- package/dist/cache/summary.js.map +1 -0
- package/dist/cache/types.d.ts +76 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +6 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/data/metrics.toon +293 -0
- package/dist/discovery.d.ts +70 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +171 -0
- package/dist/discovery.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions.d.ts +36 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +159 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plan-limits.d.ts +71 -0
- package/dist/plan-limits.d.ts.map +1 -0
- package/dist/plan-limits.js +416 -0
- package/dist/plan-limits.js.map +1 -0
- package/dist/tools/auth.d.ts +3 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +196 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/core.d.ts +3 -0
- package/dist/tools/core.d.ts.map +1 -0
- package/dist/tools/core.js +546 -0
- package/dist/tools/core.js.map +1 -0
- package/dist/utils.d.ts +45 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +76 -0
- package/dist/utils.js.map +1 -0
- package/package.json +66 -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
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# CryptoQuant MCP Server
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>On-Chain Analytics for Claude and AI Coding Agents</strong>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
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>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What is this?
|
|
16
|
+
|
|
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
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
### Quick Start (Claude Desktop, Cursor, etc.)
|
|
29
|
+
|
|
30
|
+
**Step 1**: Add to your MCP config file:
|
|
31
|
+
|
|
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` |
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"cryptoquant": {
|
|
43
|
+
"command": "npx",
|
|
44
|
+
"args": ["-y", "cryptoquant-mcp"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Step 2**: Restart your app
|
|
51
|
+
|
|
52
|
+
**Step 3**: Call `initialize()` to verify connection. Done!
|
|
53
|
+
|
|
54
|
+
### Local Development
|
|
55
|
+
|
|
56
|
+
For contributors:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/CryptoQuantOfficial/cryptoquant-mcp.git
|
|
60
|
+
cd cryptoquant-mcp
|
|
61
|
+
npm install && npm run build
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## MCP Tools
|
|
67
|
+
|
|
68
|
+
The MCP server provides these tools for API access:
|
|
69
|
+
|
|
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) |
|
|
79
|
+
|
|
80
|
+
### Supported Assets
|
|
81
|
+
|
|
82
|
+
BTC, ETH, ALT, Stablecoin, ERC20, TRX, XRP
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Natural Language Queries
|
|
87
|
+
|
|
88
|
+
Ask questions in any language - Claude will route to the right metrics:
|
|
89
|
+
|
|
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 |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Authentication
|
|
101
|
+
|
|
102
|
+
### Option A. Environment Variable (Recommended)
|
|
103
|
+
|
|
104
|
+
Add your API key to the MCP config:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"mcpServers": {
|
|
109
|
+
"cryptoquant": {
|
|
110
|
+
"command": "npx",
|
|
111
|
+
"args": ["-y", "cryptoquant-mcp"],
|
|
112
|
+
"env": {
|
|
113
|
+
"CRYPTOQUANT_API_KEY": "your-api-key"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Option B. Direct Parameter
|
|
121
|
+
|
|
122
|
+
Call `initialize()` with your API key:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
initialize(api_key="your-api-key")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The key will be saved to `~/.cryptoquant/credentials` for future sessions.
|
|
129
|
+
|
|
130
|
+
**Get your API key**: [https://cryptoquant.com/settings/api](https://cryptoquant.com/settings/api)
|
|
131
|
+
|
|
132
|
+
### Managing Credentials
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Switch accounts
|
|
136
|
+
reset_session(clear_stored=true)
|
|
137
|
+
initialize(api_key="new-api-key")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Requirements
|
|
143
|
+
|
|
144
|
+
| Component | Requirement |
|
|
145
|
+
|-----------|-------------|
|
|
146
|
+
| Node.js | v18+ |
|
|
147
|
+
| API Access | [CryptoQuant API key](https://cryptoquant.com/settings/api) |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT License - see [LICENSE](LICENSE)
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Development
|
|
158
|
+
|
|
159
|
+
### Setup
|
|
160
|
+
|
|
161
|
+
After cloning the repository, install dependencies to set up git hooks:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm install
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
This automatically configures [husky](https://typicode.github.io/husky/) for pre-commit hooks.
|
|
168
|
+
|
|
169
|
+
### Pre-commit Hooks
|
|
170
|
+
|
|
171
|
+
When committing changes to `src/`, ESLint runs automatically:
|
|
172
|
+
|
|
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`
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
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/cryptoquant-mcp/issues">Issues</a>
|
|
183
|
+
</p>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface StoredCredentials {
|
|
2
|
+
api_key: string;
|
|
3
|
+
created_at: string;
|
|
4
|
+
validated_at: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getStoredApiKey(): string | null;
|
|
7
|
+
export declare function saveApiKey(apiKey: string): void;
|
|
8
|
+
export declare function updateValidatedAt(): void;
|
|
9
|
+
export declare function clearCredentials(): void;
|
|
10
|
+
export declare function getCredentialsPath(): string;
|
|
11
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -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,53 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, chmodSync } from "fs";
|
|
4
|
+
const CREDENTIALS_DIR = join(homedir(), ".cryptoquant");
|
|
5
|
+
const CREDENTIALS_FILE = join(CREDENTIALS_DIR, "credentials");
|
|
6
|
+
export function getStoredApiKey() {
|
|
7
|
+
try {
|
|
8
|
+
if (!existsSync(CREDENTIALS_FILE))
|
|
9
|
+
return null;
|
|
10
|
+
const data = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
11
|
+
return data.api_key || null;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function saveApiKey(apiKey) {
|
|
18
|
+
if (!existsSync(CREDENTIALS_DIR)) {
|
|
19
|
+
mkdirSync(CREDENTIALS_DIR, { recursive: true, mode: 0o700 });
|
|
20
|
+
}
|
|
21
|
+
const data = {
|
|
22
|
+
api_key: apiKey,
|
|
23
|
+
created_at: new Date().toISOString(),
|
|
24
|
+
validated_at: new Date().toISOString(),
|
|
25
|
+
};
|
|
26
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(data, null, 2), { encoding: "utf-8" });
|
|
27
|
+
chmodSync(CREDENTIALS_FILE, 0o600);
|
|
28
|
+
}
|
|
29
|
+
export function updateValidatedAt() {
|
|
30
|
+
try {
|
|
31
|
+
if (!existsSync(CREDENTIALS_FILE))
|
|
32
|
+
return;
|
|
33
|
+
const data = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
34
|
+
data.validated_at = new Date().toISOString();
|
|
35
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(data, null, 2), { encoding: "utf-8" });
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Validation timestamp update is non-critical
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function clearCredentials() {
|
|
42
|
+
try {
|
|
43
|
+
if (existsSync(CREDENTIALS_FILE))
|
|
44
|
+
unlinkSync(CREDENTIALS_FILE);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Already deleted or inaccessible
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function getCredentialsPath() {
|
|
51
|
+
return CREDENTIALS_FILE;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache storage operations for discovery response caching
|
|
3
|
+
*/
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, chmodSync } from "fs";
|
|
7
|
+
import { CACHE_VERSION, CACHE_TTL_DAYS, } from "./types.js";
|
|
8
|
+
const CACHE_DIR = join(homedir(), ".cryptoquant");
|
|
9
|
+
const CACHE_FILE = join(CACHE_DIR, "discovery-cache.json");
|
|
10
|
+
/**
|
|
11
|
+
* Get cache file path.
|
|
12
|
+
*/
|
|
13
|
+
export function getCacheFilePath(_apiUrl) {
|
|
14
|
+
return CACHE_FILE;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if cache is still valid (not expired and version matches).
|
|
18
|
+
*/
|
|
19
|
+
export function isCacheValid(cache, apiUrl, apiKeyPrefix) {
|
|
20
|
+
// Version check
|
|
21
|
+
if (cache.version !== CACHE_VERSION) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// API URL must match
|
|
25
|
+
if (cache.metadata.api_url !== apiUrl) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
// API key prefix must match (detects account switch)
|
|
29
|
+
if (cache.metadata.api_key_prefix !== apiKeyPrefix) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
// TTL check
|
|
33
|
+
const expiresAt = new Date(cache.metadata.expires_at);
|
|
34
|
+
if (isNaN(expiresAt.getTime()) || expiresAt < new Date()) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read cache from file.
|
|
41
|
+
* Returns null if cache doesn't exist or is invalid JSON.
|
|
42
|
+
*/
|
|
43
|
+
export function readCache(apiUrl) {
|
|
44
|
+
const cachePath = getCacheFilePath(apiUrl);
|
|
45
|
+
try {
|
|
46
|
+
if (!existsSync(cachePath)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const data = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
50
|
+
// Basic structure validation
|
|
51
|
+
if (!data.version || !data.metadata || !data.raw_response || !data.summary) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return data;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Write cache to file with secure permissions.
|
|
62
|
+
*/
|
|
63
|
+
export function writeCache(apiUrl, apiKey, rawResponse, parsed, summary, plan) {
|
|
64
|
+
// Ensure directory exists
|
|
65
|
+
if (!existsSync(CACHE_DIR)) {
|
|
66
|
+
mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 });
|
|
67
|
+
}
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const expiresAt = new Date(now);
|
|
70
|
+
expiresAt.setDate(expiresAt.getDate() + CACHE_TTL_DAYS);
|
|
71
|
+
const cache = {
|
|
72
|
+
version: CACHE_VERSION,
|
|
73
|
+
metadata: {
|
|
74
|
+
api_url: apiUrl,
|
|
75
|
+
api_key_prefix: apiKey.slice(0, 8),
|
|
76
|
+
cached_at: now.toISOString(),
|
|
77
|
+
expires_at: expiresAt.toISOString(),
|
|
78
|
+
plan,
|
|
79
|
+
},
|
|
80
|
+
raw_response: rawResponse,
|
|
81
|
+
parsed,
|
|
82
|
+
summary,
|
|
83
|
+
};
|
|
84
|
+
const cachePath = getCacheFilePath(apiUrl);
|
|
85
|
+
writeFileSync(cachePath, JSON.stringify(cache, null, 2), { encoding: "utf-8" });
|
|
86
|
+
chmodSync(cachePath, 0o600);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Delete cache file.
|
|
90
|
+
*/
|
|
91
|
+
export function invalidateCache(apiUrl) {
|
|
92
|
+
const cachePath = getCacheFilePath(apiUrl);
|
|
93
|
+
try {
|
|
94
|
+
if (existsSync(cachePath)) {
|
|
95
|
+
unlinkSync(cachePath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Already deleted or inaccessible
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Delete the cache file.
|
|
104
|
+
*/
|
|
105
|
+
export function clearAllCaches() {
|
|
106
|
+
try {
|
|
107
|
+
if (existsSync(CACHE_FILE)) {
|
|
108
|
+
unlinkSync(CACHE_FILE);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Ignore errors
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Calculate cache age in days.
|
|
117
|
+
*/
|
|
118
|
+
export function getCacheAgeDays(cache) {
|
|
119
|
+
const cachedAt = new Date(cache.metadata.cached_at);
|
|
120
|
+
const now = new Date();
|
|
121
|
+
const diffMs = now.getTime() - cachedAt.getTime();
|
|
122
|
+
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get human-readable cache status string.
|
|
126
|
+
*/
|
|
127
|
+
export function getCacheStatus(cache, fromCache) {
|
|
128
|
+
if (!fromCache || !cache) {
|
|
129
|
+
return "fresh";
|
|
130
|
+
}
|
|
131
|
+
const days = getCacheAgeDays(cache);
|
|
132
|
+
return `cached (${days}d old)`;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get cache file path for user display.
|
|
136
|
+
*/
|
|
137
|
+
export function getCachePath() {
|
|
138
|
+
return CACHE_DIR;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/cache/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary generation for cached discovery data
|
|
3
|
+
*/
|
|
4
|
+
import type { DiscoverySummaryData, MyDiscoveryRawResponse } from "./types.js";
|
|
5
|
+
import type { PlanLimits } from "../plan-limits.js";
|
|
6
|
+
/**
|
|
7
|
+
* Generate summary from parsed plan limits.
|
|
8
|
+
* Counts endpoints and organizes by asset/category.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateSummary(limits: PlanLimits | null, statics: string[]): DiscoverySummaryData;
|
|
11
|
+
/**
|
|
12
|
+
* Extract raw response structure for caching.
|
|
13
|
+
* Only keeps necessary fields.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractRawResponse(apiResponse: Record<string, unknown>): MyDiscoveryRawResponse | null;
|
|
16
|
+
//# sourceMappingURL=summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/cache/summary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAiElG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,sBAAsB,GAAG,IAAI,CAqB/B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary generation for cached discovery data
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Generate summary from parsed plan limits.
|
|
6
|
+
* Counts endpoints and organizes by asset/category.
|
|
7
|
+
*/
|
|
8
|
+
export function generateSummary(limits, statics) {
|
|
9
|
+
const assetData = new Map();
|
|
10
|
+
// Count endpoints from limits
|
|
11
|
+
if (limits) {
|
|
12
|
+
for (const [asset, categories] of Object.entries(limits)) {
|
|
13
|
+
if (!assetData.has(asset)) {
|
|
14
|
+
assetData.set(asset, { endpoint_count: 0, categories: new Set() });
|
|
15
|
+
}
|
|
16
|
+
const data = assetData.get(asset);
|
|
17
|
+
for (const [category, metrics] of Object.entries(categories)) {
|
|
18
|
+
data.categories.add(category);
|
|
19
|
+
if (metrics) {
|
|
20
|
+
data.endpoint_count += Object.keys(metrics).length;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Count static endpoints (parse asset from path)
|
|
26
|
+
for (const staticPath of statics) {
|
|
27
|
+
const parts = staticPath.split("/");
|
|
28
|
+
if (parts.length >= 4) {
|
|
29
|
+
const asset = parts[2];
|
|
30
|
+
const category = parts[3];
|
|
31
|
+
if (!assetData.has(asset)) {
|
|
32
|
+
assetData.set(asset, { endpoint_count: 0, categories: new Set() });
|
|
33
|
+
}
|
|
34
|
+
const data = assetData.get(asset);
|
|
35
|
+
data.endpoint_count++;
|
|
36
|
+
data.categories.add(category);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Build summary
|
|
40
|
+
const assets = [];
|
|
41
|
+
const categoryByAsset = {};
|
|
42
|
+
let totalEndpoints = 0;
|
|
43
|
+
for (const [asset, data] of assetData.entries()) {
|
|
44
|
+
assets.push({
|
|
45
|
+
name: asset,
|
|
46
|
+
endpoint_count: data.endpoint_count,
|
|
47
|
+
categories: Array.from(data.categories).sort(),
|
|
48
|
+
});
|
|
49
|
+
categoryByAsset[asset] = Array.from(data.categories).sort();
|
|
50
|
+
totalEndpoints += data.endpoint_count;
|
|
51
|
+
}
|
|
52
|
+
// Sort assets alphabetically
|
|
53
|
+
assets.sort((a, b) => a.name.localeCompare(b.name));
|
|
54
|
+
return {
|
|
55
|
+
total_endpoints: totalEndpoints,
|
|
56
|
+
assets,
|
|
57
|
+
category_by_asset: categoryByAsset,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extract raw response structure for caching.
|
|
62
|
+
* Only keeps necessary fields.
|
|
63
|
+
*/
|
|
64
|
+
export function extractRawResponse(apiResponse) {
|
|
65
|
+
try {
|
|
66
|
+
const apiEndpoint = apiResponse.apiEndpoint;
|
|
67
|
+
const plan = apiResponse.plan;
|
|
68
|
+
const apiRateLimit = apiResponse.apiRateLimit;
|
|
69
|
+
if (!apiEndpoint || typeof apiEndpoint !== "object") {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
apiEndpoint: apiEndpoint,
|
|
74
|
+
plan: { name: plan?.name || "unknown" },
|
|
75
|
+
apiRateLimit: {
|
|
76
|
+
token: apiRateLimit?.token || 0,
|
|
77
|
+
window: apiRateLimit?.window || "day",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/cache/summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache schema types for CryptoQuant discovery caching
|
|
3
|
+
*/
|
|
4
|
+
import type { UserPlan, ApiRateLimit, PlanLimits } from "../plan-limits.js";
|
|
5
|
+
export declare const CACHE_VERSION = 1;
|
|
6
|
+
export declare const CACHE_TTL_DAYS = 7;
|
|
7
|
+
/**
|
|
8
|
+
* Raw API response structure from /my/discovery/endpoints
|
|
9
|
+
*/
|
|
10
|
+
export interface MyDiscoveryRawResponse {
|
|
11
|
+
apiEndpoint: Record<string, unknown>;
|
|
12
|
+
plan: {
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
apiRateLimit: {
|
|
16
|
+
token: number;
|
|
17
|
+
window: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Summary data generated from the raw response
|
|
22
|
+
*/
|
|
23
|
+
export interface DiscoverySummaryData {
|
|
24
|
+
total_endpoints: number;
|
|
25
|
+
assets: Array<{
|
|
26
|
+
name: string;
|
|
27
|
+
endpoint_count: number;
|
|
28
|
+
categories: string[];
|
|
29
|
+
}>;
|
|
30
|
+
category_by_asset: Record<string, string[]>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Cache metadata for validation
|
|
34
|
+
*/
|
|
35
|
+
export interface CacheMetadata {
|
|
36
|
+
api_url: string;
|
|
37
|
+
api_key_prefix: string;
|
|
38
|
+
cached_at: string;
|
|
39
|
+
expires_at: string;
|
|
40
|
+
plan: UserPlan;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Full cache schema stored in file
|
|
44
|
+
*/
|
|
45
|
+
export interface DiscoveryCacheSchema {
|
|
46
|
+
version: typeof CACHE_VERSION;
|
|
47
|
+
metadata: CacheMetadata;
|
|
48
|
+
raw_response: MyDiscoveryRawResponse;
|
|
49
|
+
parsed: {
|
|
50
|
+
limits: PlanLimits | null;
|
|
51
|
+
statics: string[];
|
|
52
|
+
apiRateLimit: ApiRateLimit | null;
|
|
53
|
+
};
|
|
54
|
+
summary: DiscoverySummaryData;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compact response format for initialize() tool
|
|
58
|
+
*/
|
|
59
|
+
export interface CompactInitializeResponse {
|
|
60
|
+
success: boolean;
|
|
61
|
+
session: {
|
|
62
|
+
plan: UserPlan;
|
|
63
|
+
rate_limit: string;
|
|
64
|
+
cache_status: string;
|
|
65
|
+
};
|
|
66
|
+
scope: {
|
|
67
|
+
total_endpoints: number;
|
|
68
|
+
accessible: number;
|
|
69
|
+
assets: Record<string, {
|
|
70
|
+
endpoints: number;
|
|
71
|
+
categories: number;
|
|
72
|
+
}>;
|
|
73
|
+
note: string;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cache/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE5E,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC,CAAC;IACH,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,sBAAsB,CAAC;IACrC,MAAM,EAAE;QACN,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;KACnC,CAAC;IACF,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE;QACP,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CACZ,MAAM,EACN;YACE,SAAS,EAAE,MAAM,CAAC;YAClB,UAAU,EAAE,MAAM,CAAC;SACpB,CACF,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH"}
|