@cryptoquant_official/mcp 0.0.5 → 0.0.6-alpha2
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 +329 -59
- package/dist/ai-sdk/anthropic.d.ts +125 -0
- package/dist/ai-sdk/anthropic.d.ts.map +1 -0
- package/dist/ai-sdk/anthropic.js +278 -0
- package/dist/ai-sdk/anthropic.js.map +1 -0
- package/dist/ai-sdk/execute.d.ts +35 -0
- package/dist/ai-sdk/execute.d.ts.map +1 -0
- package/dist/ai-sdk/execute.js +531 -0
- package/dist/ai-sdk/execute.js.map +1 -0
- package/dist/ai-sdk/index.d.ts +51 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +53 -0
- package/dist/ai-sdk/index.js.map +1 -0
- package/dist/ai-sdk/prompts.d.ts +34 -0
- package/dist/ai-sdk/prompts.d.ts.map +1 -0
- package/dist/ai-sdk/prompts.js +74 -0
- package/dist/ai-sdk/prompts.js.map +1 -0
- package/dist/ai-sdk/schemas.d.ts +66 -0
- package/dist/ai-sdk/schemas.d.ts.map +1 -0
- package/dist/ai-sdk/schemas.js +136 -0
- package/dist/ai-sdk/schemas.js.map +1 -0
- package/dist/ai-sdk/tools.d.ts +165 -0
- package/dist/ai-sdk/tools.d.ts.map +1 -0
- package/dist/ai-sdk/tools.js +152 -0
- package/dist/ai-sdk/tools.js.map +1 -0
- package/dist/ai-sdk/types.d.ts +149 -0
- package/dist/ai-sdk/types.d.ts.map +1 -0
- package/dist/ai-sdk/types.js +5 -0
- package/dist/ai-sdk/types.js.map +1 -0
- package/dist/core/auth/storage.d.ts.map +1 -0
- package/dist/core/auth/storage.js.map +1 -0
- package/dist/core/cache/storage.d.ts +110 -0
- package/dist/core/cache/storage.d.ts.map +1 -0
- package/dist/core/cache/storage.js +356 -0
- package/dist/core/cache/storage.js.map +1 -0
- package/dist/core/cache/summary.d.ts.map +1 -0
- package/dist/core/cache/summary.js.map +1 -0
- package/dist/{cache → core/cache}/types.d.ts +25 -0
- package/dist/{cache → core/cache}/types.d.ts.map +1 -1
- package/dist/core/cache/types.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +19 -0
- package/dist/core/index.js.map +1 -0
- package/dist/{permissions.d.ts → core/permissions.d.ts} +1 -1
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/{permissions.js → core/permissions.js} +6 -6
- package/dist/core/permissions.js.map +1 -0
- package/dist/core/plan-limits.d.ts.map +1 -0
- package/dist/core/plan-limits.js.map +1 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/{utils.js → core/utils.js} +2 -2
- package/dist/core/utils.js.map +1 -0
- package/dist/http/chat-proxy.d.ts +32 -0
- package/dist/http/chat-proxy.d.ts.map +1 -0
- package/dist/http/chat-proxy.js +310 -0
- package/dist/http/chat-proxy.js.map +1 -0
- package/dist/http/index.d.ts +12 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +30 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/server.d.ts +20 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +231 -0
- package/dist/http/server.js.map +1 -0
- package/dist/shared/index.d.ts +164 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +79 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/intent-routing.generated.d.ts +40 -0
- package/dist/shared/intent-routing.generated.d.ts.map +1 -0
- package/dist/shared/intent-routing.generated.js +518 -0
- package/dist/shared/intent-routing.generated.js.map +1 -0
- package/dist/shared/metrics-data.generated.d.ts +176 -0
- package/dist/shared/metrics-data.generated.d.ts.map +1 -0
- package/dist/shared/metrics-data.generated.js +3077 -0
- package/dist/shared/metrics-data.generated.js.map +1 -0
- package/dist/shared/skill-prompts.generated.d.ts +38 -0
- package/dist/shared/skill-prompts.generated.d.ts.map +1 -0
- package/dist/shared/skill-prompts.generated.js +89 -0
- package/dist/shared/skill-prompts.generated.js.map +1 -0
- package/dist/shared/workflows.generated.d.ts +48 -0
- package/dist/shared/workflows.generated.d.ts.map +1 -0
- package/dist/shared/workflows.generated.js +352 -0
- package/dist/shared/workflows.generated.js.map +1 -0
- package/dist/stdio/index.d.ts +10 -0
- package/dist/stdio/index.d.ts.map +1 -0
- package/dist/stdio/index.js +30 -0
- package/dist/stdio/index.js.map +1 -0
- package/dist/stdio/tools/auth.d.ts.map +1 -0
- package/dist/{tools → stdio/tools}/auth.js +10 -8
- package/dist/stdio/tools/auth.js.map +1 -0
- package/dist/stdio/tools/core.d.ts.map +1 -0
- package/dist/{tools → stdio/tools}/core.js +32 -145
- package/dist/stdio/tools/core.js.map +1 -0
- package/package.json +52 -13
- package/dist/auth/storage.d.ts.map +0 -1
- package/dist/auth/storage.js.map +0 -1
- package/dist/cache/storage.d.ts +0 -47
- package/dist/cache/storage.d.ts.map +0 -1
- package/dist/cache/storage.js +0 -140
- package/dist/cache/storage.js.map +0 -1
- package/dist/cache/summary.d.ts.map +0 -1
- package/dist/cache/summary.js.map +0 -1
- package/dist/cache/types.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/discovery.d.ts.map +0 -1
- package/dist/discovery.js.map +0 -1
- package/dist/index.d.ts +0 -18
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -47
- package/dist/index.js.map +0 -1
- package/dist/permissions.d.ts.map +0 -1
- package/dist/permissions.js.map +0 -1
- package/dist/plan-limits.d.ts.map +0 -1
- package/dist/plan-limits.js.map +0 -1
- package/dist/tools/auth.d.ts.map +0 -1
- package/dist/tools/auth.js.map +0 -1
- package/dist/tools/core.d.ts.map +0 -1
- package/dist/tools/core.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- /package/dist/{auth → core/auth}/storage.d.ts +0 -0
- /package/dist/{auth → core/auth}/storage.js +0 -0
- /package/dist/{cache → core/cache}/summary.d.ts +0 -0
- /package/dist/{cache → core/cache}/summary.js +0 -0
- /package/dist/{cache → core/cache}/types.js +0 -0
- /package/dist/{config.d.ts → core/config.d.ts} +0 -0
- /package/dist/{config.js → core/config.js} +0 -0
- /package/dist/{discovery.d.ts → core/discovery.d.ts} +0 -0
- /package/dist/{discovery.js → core/discovery.js} +0 -0
- /package/dist/{plan-limits.d.ts → core/plan-limits.d.ts} +0 -0
- /package/dist/{plan-limits.js → core/plan-limits.js} +0 -0
- /package/dist/{utils.d.ts → core/utils.d.ts} +0 -0
- /package/dist/{tools → stdio/tools}/auth.d.ts +0 -0
- /package/dist/{tools → stdio/tools}/core.d.ts +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HTTP module - HTTP server and chat proxy
|
|
4
|
+
*
|
|
5
|
+
* Can be used as:
|
|
6
|
+
* 1. Standalone: node dist/http/index.js
|
|
7
|
+
* 2. Library: import { startHttpServer } from '@cryptoquant_official/mcp/http'
|
|
8
|
+
*/
|
|
9
|
+
export { startHttpServer, cleanupStaleSessions } from "./server.js";
|
|
10
|
+
export { handleChat, getToolsSchema } from "./chat-proxy.js";
|
|
11
|
+
export type { ChatRequest, ChatResponse, ToolCall } from "./chat-proxy.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAKH,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HTTP module - HTTP server and chat proxy
|
|
4
|
+
*
|
|
5
|
+
* Can be used as:
|
|
6
|
+
* 1. Standalone: node dist/http/index.js
|
|
7
|
+
* 2. Library: import { startHttpServer } from '@cryptoquant_official/mcp/http'
|
|
8
|
+
*/
|
|
9
|
+
import { logger } from "../core/utils.js";
|
|
10
|
+
// Re-exports for library usage
|
|
11
|
+
export { startHttpServer, cleanupStaleSessions } from "./server.js";
|
|
12
|
+
export { handleChat, getToolsSchema } from "./chat-proxy.js";
|
|
13
|
+
/**
|
|
14
|
+
* HTTP server main entry point
|
|
15
|
+
*/
|
|
16
|
+
async function main() {
|
|
17
|
+
const { startHttpServer } = await import("./server.js");
|
|
18
|
+
await startHttpServer({
|
|
19
|
+
port: parseInt(process.env.MCP_HTTP_PORT ?? "3100", 10),
|
|
20
|
+
host: process.env.MCP_HTTP_HOST ?? "127.0.0.1",
|
|
21
|
+
corsOrigins: process.env.MCP_CORS_ORIGINS ?? "http://localhost:3000,http://localhost:5173",
|
|
22
|
+
enableLegacySse: process.env.MCP_ENABLE_LEGACY_SSE === "true",
|
|
23
|
+
});
|
|
24
|
+
logger.info("CryptoQuant HTTP Server started");
|
|
25
|
+
}
|
|
26
|
+
main().catch((error) => {
|
|
27
|
+
logger.error("Failed to start HTTP server:", error);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,+BAA+B;AAC/B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAExD,MAAM,eAAe,CAAC;QACpB,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,MAAM,EAAE,EAAE,CAAC;QACvD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,WAAW;QAC9C,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,6CAA6C;QAC1F,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,MAAM;KAC9D,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;AACjD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Transport Server for MCP
|
|
3
|
+
* Enables web applications to connect to the MCP server via HTTP/SSE
|
|
4
|
+
*/
|
|
5
|
+
interface HttpServerConfig {
|
|
6
|
+
port?: number;
|
|
7
|
+
host?: string;
|
|
8
|
+
corsOrigins?: string | string[];
|
|
9
|
+
enableLegacySse?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Start HTTP server with Streamable HTTP transport
|
|
13
|
+
*/
|
|
14
|
+
export declare function startHttpServer(config?: HttpServerConfig): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Clean up stale sessions (older than 1 hour)
|
|
17
|
+
*/
|
|
18
|
+
export declare function cleanupStaleSessions(): void;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/http/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA4BD;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqNlF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAW3C"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Transport Server for MCP
|
|
3
|
+
* Enables web applications to connect to the MCP server via HTTP/SSE
|
|
4
|
+
*/
|
|
5
|
+
import express from "express";
|
|
6
|
+
import cors from "cors";
|
|
7
|
+
import rateLimit from "express-rate-limit";
|
|
8
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
10
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
11
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
13
|
+
import { registerAuthTools } from "../stdio/tools/auth.js";
|
|
14
|
+
import { registerCoreTools } from "../stdio/tools/core.js";
|
|
15
|
+
import { logger } from "../core/utils.js";
|
|
16
|
+
import { handleChat, getToolsSchema } from "./chat-proxy.js";
|
|
17
|
+
// Session storage for Streamable HTTP
|
|
18
|
+
const sessions = new Map();
|
|
19
|
+
// Legacy SSE transport storage - Map for multi-client support
|
|
20
|
+
const legacySseSessions = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Create and configure the MCP server instance
|
|
23
|
+
*/
|
|
24
|
+
function createMcpServer() {
|
|
25
|
+
const server = new McpServer({
|
|
26
|
+
name: "cryptoquant",
|
|
27
|
+
version: "1.0.0",
|
|
28
|
+
});
|
|
29
|
+
registerAuthTools(server);
|
|
30
|
+
registerCoreTools(server);
|
|
31
|
+
return server;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Start HTTP server with Streamable HTTP transport
|
|
35
|
+
*/
|
|
36
|
+
export async function startHttpServer(config = {}) {
|
|
37
|
+
const port = config.port ?? parseInt(process.env.MCP_HTTP_PORT ?? "3100", 10);
|
|
38
|
+
const host = config.host ?? process.env.MCP_HTTP_HOST ?? "127.0.0.1";
|
|
39
|
+
const corsOriginsRaw = config.corsOrigins ?? process.env.MCP_CORS_ORIGINS ?? "http://localhost:3000,http://localhost:5173";
|
|
40
|
+
// Parse comma-separated origins into array, or use as-is if already an array
|
|
41
|
+
const corsOrigins = Array.isArray(corsOriginsRaw)
|
|
42
|
+
? corsOriginsRaw
|
|
43
|
+
: corsOriginsRaw.split(",").map((origin) => origin.trim());
|
|
44
|
+
const enableLegacySse = config.enableLegacySse ?? process.env.MCP_ENABLE_LEGACY_SSE === "true";
|
|
45
|
+
const app = express();
|
|
46
|
+
// Rate limiting - general limiter for all routes
|
|
47
|
+
const generalLimiter = rateLimit({
|
|
48
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
49
|
+
max: 100, // 100 requests per 15 minutes
|
|
50
|
+
message: { error: "Too many requests, please try again later" },
|
|
51
|
+
standardHeaders: true,
|
|
52
|
+
legacyHeaders: false,
|
|
53
|
+
});
|
|
54
|
+
// Stricter rate limit for /chat endpoint (uses external API)
|
|
55
|
+
const chatLimiter = rateLimit({
|
|
56
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
57
|
+
max: 30, // 30 requests per 15 minutes
|
|
58
|
+
message: { error: "Too many chat requests, please try again later" },
|
|
59
|
+
standardHeaders: true,
|
|
60
|
+
legacyHeaders: false,
|
|
61
|
+
});
|
|
62
|
+
// Middleware
|
|
63
|
+
app.use(generalLimiter);
|
|
64
|
+
app.use(cors({
|
|
65
|
+
origin: corsOrigins,
|
|
66
|
+
credentials: true,
|
|
67
|
+
exposedHeaders: ["mcp-session-id"],
|
|
68
|
+
}));
|
|
69
|
+
app.use(express.json());
|
|
70
|
+
// Health check endpoint - minimal info to avoid information disclosure
|
|
71
|
+
app.get("/health", (_req, res) => {
|
|
72
|
+
res.json({ status: "ok" });
|
|
73
|
+
});
|
|
74
|
+
// =========================================================================
|
|
75
|
+
// Chat Proxy Endpoints (Claude API Integration)
|
|
76
|
+
// =========================================================================
|
|
77
|
+
// POST /chat - Chat with Claude + automatic tool execution
|
|
78
|
+
app.post("/chat", chatLimiter, async (req, res) => {
|
|
79
|
+
const chatRequest = req.body;
|
|
80
|
+
if (!chatRequest.message) {
|
|
81
|
+
res.status(400).json({ error: "message is required" });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (!chatRequest.claude_api_key) {
|
|
85
|
+
res.status(400).json({ error: "claude_api_key is required" });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const result = await handleChat(chatRequest);
|
|
90
|
+
res.json(result);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
// Only log error message, not full error object to avoid leaking sensitive data
|
|
94
|
+
const errorMessage = error instanceof Error ? error.message : "Chat request failed";
|
|
95
|
+
logger.error("[/chat] error:", errorMessage);
|
|
96
|
+
res.status(500).json({
|
|
97
|
+
success: false,
|
|
98
|
+
error: errorMessage,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// GET /tools/schema - Get Claude-compatible tool definitions
|
|
103
|
+
app.get("/tools/schema", (_req, res) => {
|
|
104
|
+
res.json({
|
|
105
|
+
tools: getToolsSchema(),
|
|
106
|
+
usage: "Use these tool definitions with Claude API's tool_use feature",
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
// =========================================================================
|
|
110
|
+
// Streamable HTTP Transport (Modern)
|
|
111
|
+
// =========================================================================
|
|
112
|
+
// POST /mcp - Handle MCP requests
|
|
113
|
+
app.post("/mcp", async (req, res) => {
|
|
114
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
115
|
+
const session = sessionId ? sessions.get(sessionId) : undefined;
|
|
116
|
+
// Check if this is an initialization request
|
|
117
|
+
const isInit = isInitializeRequest(req.body);
|
|
118
|
+
if (isInit || !session) {
|
|
119
|
+
// Create new session
|
|
120
|
+
const newSessionId = randomUUID();
|
|
121
|
+
const server = createMcpServer();
|
|
122
|
+
const transport = new StreamableHTTPServerTransport({
|
|
123
|
+
sessionIdGenerator: () => newSessionId,
|
|
124
|
+
onsessioninitialized: (id) => {
|
|
125
|
+
logger.info(`Session initialized: ${id}`);
|
|
126
|
+
sessions.set(id, { transport, createdAt: Date.now() });
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
transport.onclose = () => {
|
|
130
|
+
logger.info(`Session closed: ${newSessionId}`);
|
|
131
|
+
sessions.delete(newSessionId);
|
|
132
|
+
};
|
|
133
|
+
await server.connect(transport);
|
|
134
|
+
await transport.handleRequest(req, res, req.body);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Use existing session
|
|
138
|
+
await session.transport.handleRequest(req, res, req.body);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// GET /mcp - SSE stream for server-to-client notifications
|
|
142
|
+
app.get("/mcp", async (req, res) => {
|
|
143
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
144
|
+
if (!sessionId) {
|
|
145
|
+
res.status(400).json({ error: "Missing mcp-session-id header" });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const session = sessions.get(sessionId);
|
|
149
|
+
if (!session) {
|
|
150
|
+
res.status(404).json({ error: "Session not found" });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
await session.transport.handleRequest(req, res);
|
|
154
|
+
});
|
|
155
|
+
// DELETE /mcp - Close session
|
|
156
|
+
app.delete("/mcp", async (req, res) => {
|
|
157
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
158
|
+
if (!sessionId) {
|
|
159
|
+
res.status(400).json({ error: "Missing mcp-session-id header" });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const session = sessions.get(sessionId);
|
|
163
|
+
if (!session) {
|
|
164
|
+
res.status(404).json({ error: "Session not found" });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
await session.transport.close();
|
|
168
|
+
sessions.delete(sessionId);
|
|
169
|
+
res.status(204).send();
|
|
170
|
+
});
|
|
171
|
+
// =========================================================================
|
|
172
|
+
// Legacy SSE Transport (for backwards compatibility)
|
|
173
|
+
// =========================================================================
|
|
174
|
+
if (enableLegacySse) {
|
|
175
|
+
// GET /sse - Establish SSE connection
|
|
176
|
+
app.get("/sse", async (_req, res) => {
|
|
177
|
+
const sessionId = randomUUID();
|
|
178
|
+
logger.info(`Legacy SSE connection requested: ${sessionId}`);
|
|
179
|
+
const server = createMcpServer();
|
|
180
|
+
// Include session ID in the messages endpoint path
|
|
181
|
+
const transport = new SSEServerTransport(`/messages?sessionId=${sessionId}`, res);
|
|
182
|
+
legacySseSessions.set(sessionId, transport);
|
|
183
|
+
transport.onclose = () => {
|
|
184
|
+
logger.info(`Legacy SSE connection closed: ${sessionId}`);
|
|
185
|
+
legacySseSessions.delete(sessionId);
|
|
186
|
+
};
|
|
187
|
+
await server.connect(transport);
|
|
188
|
+
});
|
|
189
|
+
// POST /messages - Handle client messages for legacy SSE
|
|
190
|
+
app.post("/messages", async (req, res) => {
|
|
191
|
+
const sessionId = req.query.sessionId;
|
|
192
|
+
if (!sessionId) {
|
|
193
|
+
res.status(400).json({ error: "Missing sessionId query parameter" });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const transport = legacySseSessions.get(sessionId);
|
|
197
|
+
if (!transport) {
|
|
198
|
+
res.status(404).json({ error: "Session not found or expired" });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
await transport.handlePostMessage(req, res);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Start server
|
|
205
|
+
app.listen(port, host, () => {
|
|
206
|
+
logger.info(`CryptoQuant MCP HTTP Server running at http://${host}:${port}`);
|
|
207
|
+
logger.info(` - Chat Proxy: POST /chat`);
|
|
208
|
+
logger.info(` - Tool Schema: GET /tools/schema`);
|
|
209
|
+
logger.info(` - Streamable HTTP: POST/GET/DELETE /mcp`);
|
|
210
|
+
if (enableLegacySse) {
|
|
211
|
+
logger.info(` - Legacy SSE: GET /sse, POST /messages`);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Clean up stale sessions (older than 1 hour)
|
|
217
|
+
*/
|
|
218
|
+
export function cleanupStaleSessions() {
|
|
219
|
+
const maxAge = 60 * 60 * 1000; // 1 hour
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
for (const [id, session] of sessions) {
|
|
222
|
+
if (now - session.createdAt > maxAge) {
|
|
223
|
+
logger.info(`Cleaning up stale session: ${id}`);
|
|
224
|
+
session.transport.close();
|
|
225
|
+
sessions.delete(id);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Run cleanup every 15 minutes
|
|
230
|
+
setInterval(cleanupStaleSessions, 15 * 60 * 1000);
|
|
231
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/http/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CryptoQuant Shared Data Module
|
|
3
|
+
*
|
|
4
|
+
* Unified exports for metrics, intents, workflows, and skills.
|
|
5
|
+
* Import from this file instead of individual generated files.
|
|
6
|
+
*/
|
|
7
|
+
import { METRIC_DEFINITIONS, SCORING_RULES, INTERPRETATION_SYSTEM_PROMPT, calculateScore, calculateTradingSignal, getMetricSignal, getMetricDefinition, getAvailableMetrics } from "./metrics-data.generated.js";
|
|
8
|
+
import type { MetricDefinition, MetricThreshold, MetricScoring, ScoringRule } from "./metrics-data.generated.js";
|
|
9
|
+
import { INTENT_ROUTING, matchIntent, getEndpointsForIntent, getIntentByMetric, getAvailableIntents } from "./intent-routing.generated.js";
|
|
10
|
+
import type { IntentConfig, AdditionalMetric } from "./intent-routing.generated.js";
|
|
11
|
+
import { ANALYSIS_WORKFLOWS, getLayersForDepth, getWorkflowEndpoints, getEndpointsForDepth, matchWorkflow, getAvailableWorkflows } from "./workflows.generated.js";
|
|
12
|
+
import type { AnalysisWorkflow, AnalysisLayer, WorkflowMetric, AnalysisDepth } from "./workflows.generated.js";
|
|
13
|
+
import { SKILL_PROMPTS, getSkillPrompt, getSkillMetadata, getAvailableSkills, toMcpPrompt } from "./skill-prompts.generated.js";
|
|
14
|
+
import type { SkillPrompt } from "./skill-prompts.generated.js";
|
|
15
|
+
/**
|
|
16
|
+
* All CryptoQuant data in one object
|
|
17
|
+
*/
|
|
18
|
+
export declare const CRYPTOQUANT_DATA: {
|
|
19
|
+
readonly metrics: Record<string, MetricDefinition>;
|
|
20
|
+
readonly scoring: Record<string, MetricScoring>;
|
|
21
|
+
readonly thresholds: {
|
|
22
|
+
readonly market: {
|
|
23
|
+
mvrv: {
|
|
24
|
+
bullish: {
|
|
25
|
+
max: number;
|
|
26
|
+
};
|
|
27
|
+
neutral: {
|
|
28
|
+
min: number;
|
|
29
|
+
max: number;
|
|
30
|
+
};
|
|
31
|
+
bearish: {
|
|
32
|
+
min: number;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
sopr: {
|
|
36
|
+
bullish: {
|
|
37
|
+
max: number;
|
|
38
|
+
};
|
|
39
|
+
neutral: {
|
|
40
|
+
min: number;
|
|
41
|
+
max: number;
|
|
42
|
+
};
|
|
43
|
+
bearish: {
|
|
44
|
+
min: number;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
netflow: {
|
|
48
|
+
bullish: {
|
|
49
|
+
max: number;
|
|
50
|
+
};
|
|
51
|
+
neutral: {
|
|
52
|
+
min: number;
|
|
53
|
+
max: number;
|
|
54
|
+
};
|
|
55
|
+
bearish: {
|
|
56
|
+
min: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
readonly whale: {
|
|
61
|
+
ratio: {
|
|
62
|
+
retail: {
|
|
63
|
+
max: number;
|
|
64
|
+
};
|
|
65
|
+
mixed: {
|
|
66
|
+
min: number;
|
|
67
|
+
max: number;
|
|
68
|
+
};
|
|
69
|
+
whaleHeavy: {
|
|
70
|
+
min: number;
|
|
71
|
+
max: number;
|
|
72
|
+
};
|
|
73
|
+
whaleDominated: {
|
|
74
|
+
min: number;
|
|
75
|
+
max: number;
|
|
76
|
+
};
|
|
77
|
+
extreme: {
|
|
78
|
+
min: number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
readonly cycle: {
|
|
83
|
+
accumulation: {
|
|
84
|
+
name: string;
|
|
85
|
+
mvrv: string;
|
|
86
|
+
sopr: string;
|
|
87
|
+
netflow: string;
|
|
88
|
+
};
|
|
89
|
+
markupEarlyBull: {
|
|
90
|
+
name: string;
|
|
91
|
+
mvrv: string;
|
|
92
|
+
sopr: string;
|
|
93
|
+
netflow: string;
|
|
94
|
+
};
|
|
95
|
+
distribution: {
|
|
96
|
+
name: string;
|
|
97
|
+
mvrv: string;
|
|
98
|
+
sopr: string;
|
|
99
|
+
netflow: string;
|
|
100
|
+
};
|
|
101
|
+
markdownBear: {
|
|
102
|
+
name: string;
|
|
103
|
+
mvrv: string;
|
|
104
|
+
sopr: string;
|
|
105
|
+
netflow: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
readonly signal: {
|
|
109
|
+
readonly bullish: {
|
|
110
|
+
readonly emoji: "🟢";
|
|
111
|
+
readonly label: "Bullish / Buy opportunity";
|
|
112
|
+
readonly action: "Consider accumulating";
|
|
113
|
+
};
|
|
114
|
+
readonly neutral: {
|
|
115
|
+
readonly emoji: "🟡";
|
|
116
|
+
readonly label: "Neutral";
|
|
117
|
+
readonly action: "Hold / Wait for clearer signal";
|
|
118
|
+
};
|
|
119
|
+
readonly caution: {
|
|
120
|
+
readonly emoji: "🟠";
|
|
121
|
+
readonly label: "Caution";
|
|
122
|
+
readonly action: "Be cautious, potential reversal";
|
|
123
|
+
};
|
|
124
|
+
readonly bearish: {
|
|
125
|
+
readonly emoji: "🔴";
|
|
126
|
+
readonly label: "Bearish / Sell signal";
|
|
127
|
+
readonly action: "Consider reducing exposure";
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
readonly intents: Record<string, IntentConfig>;
|
|
132
|
+
readonly workflows: Record<string, AnalysisWorkflow>;
|
|
133
|
+
readonly skills: Record<string, SkillPrompt>;
|
|
134
|
+
readonly prompts: {
|
|
135
|
+
readonly interpretation: "\nYou are a crypto market analyst with access to CryptoQuant on-chain data.\n\n## Key Metrics Interpretation\n\n### Valuation (MVRV)\n- < 1.0: 🟢 Undervalued (buy zone)\n- 1.0-2.5: 🟡 Fair value\n- > 3.5: 🔴 Overheated (sell zone)\n\n### Profit Behavior (SOPR)\n- < 0.95: 🟢 Capitulation (contrarian buy)\n- 0.95-1.05: 🟡 Normal\n- > 1.10: 🔴 Heavy profit taking\n\n### Exchange Flows (Netflow)\n- < -1,000 BTC: 🟢 Accumulation\n- ±1,000 BTC: 🟡 Neutral\n- > +5,000 BTC: 🔴 Distribution\n\n### Funding Rate\n- < -0.03%: 🟢 Shorts overcrowded\n- ±0.01%: 🟡 Neutral\n- > 0.05%: 🔴 Longs overcrowded\n\n## Trading Signal Weights\n- MVRV: 30%\n- SOPR: 25%\n- Netflow: 25%\n- Funding: 20%\n\nScore > 70: BUY | 40-70: HOLD | < 40: SELL\n\n## Important Notes\n- No single metric is definitive - use multiple confirmations\n- Context matters - same values mean different things in bull vs bear\n- This is not financial advice - metrics are informational only\n";
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Helper functions for working with CryptoQuant data
|
|
140
|
+
*/
|
|
141
|
+
export declare const CryptoQuantHelpers: {
|
|
142
|
+
readonly calculateScore: typeof calculateScore;
|
|
143
|
+
readonly calculateTradingSignal: typeof calculateTradingSignal;
|
|
144
|
+
readonly getMetricSignal: typeof getMetricSignal;
|
|
145
|
+
readonly getMetricDefinition: typeof getMetricDefinition;
|
|
146
|
+
readonly getAvailableMetrics: typeof getAvailableMetrics;
|
|
147
|
+
readonly matchIntent: typeof matchIntent;
|
|
148
|
+
readonly getEndpointsForIntent: typeof getEndpointsForIntent;
|
|
149
|
+
readonly getIntentByMetric: typeof getIntentByMetric;
|
|
150
|
+
readonly getAvailableIntents: typeof getAvailableIntents;
|
|
151
|
+
readonly getLayersForDepth: typeof getLayersForDepth;
|
|
152
|
+
readonly getWorkflowEndpoints: typeof getWorkflowEndpoints;
|
|
153
|
+
readonly getEndpointsForDepth: typeof getEndpointsForDepth;
|
|
154
|
+
readonly matchWorkflow: typeof matchWorkflow;
|
|
155
|
+
readonly getAvailableWorkflows: typeof getAvailableWorkflows;
|
|
156
|
+
readonly getSkillPrompt: typeof getSkillPrompt;
|
|
157
|
+
readonly getSkillMetadata: typeof getSkillMetadata;
|
|
158
|
+
readonly getAvailableSkills: typeof getAvailableSkills;
|
|
159
|
+
readonly toMcpPrompt: typeof toMcpPrompt;
|
|
160
|
+
};
|
|
161
|
+
export type { MetricDefinition, MetricThreshold, MetricScoring, ScoringRule, IntentConfig, AdditionalMetric, AnalysisWorkflow, AnalysisLayer, WorkflowMetric, AnalysisDepth, SkillPrompt, };
|
|
162
|
+
export { METRIC_DEFINITIONS, SCORING_RULES, INTERPRETATION_SYSTEM_PROMPT, INTENT_ROUTING, ANALYSIS_WORKFLOWS, SKILL_PROMPTS, };
|
|
163
|
+
export { calculateScore, calculateTradingSignal, getMetricSignal, getMetricDefinition, getAvailableMetrics, matchIntent, matchWorkflow, getSkillPrompt, };
|
|
164
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACL,kBAAkB,EAClB,aAAa,EAKb,4BAA4B,EAC5B,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,EACZ,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,aAAa,EACd,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAMhE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BnB,CAAC;AAMX;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;CA0BrB,CAAC;AAMX,YAAY,EAEV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,EAEX,YAAY,EACZ,gBAAgB,EAEhB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,aAAa,EAEb,WAAW,GACZ,CAAC;AAOF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,4BAA4B,EAC5B,cAAc,EACd,kBAAkB,EAClB,aAAa,GACd,CAAC;AAGF,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,cAAc,GACf,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CryptoQuant Shared Data Module
|
|
3
|
+
*
|
|
4
|
+
* Unified exports for metrics, intents, workflows, and skills.
|
|
5
|
+
* Import from this file instead of individual generated files.
|
|
6
|
+
*/
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Import all generated data
|
|
9
|
+
// =============================================================================
|
|
10
|
+
import { METRIC_DEFINITIONS, SCORING_RULES, SIGNAL_LEGEND, MARKET_THRESHOLDS, WHALE_THRESHOLDS, CYCLE_PHASES, INTERPRETATION_SYSTEM_PROMPT, calculateScore, calculateTradingSignal, getMetricSignal, getMetricDefinition, getAvailableMetrics, } from "./metrics-data.generated.js";
|
|
11
|
+
import { INTENT_ROUTING, matchIntent, getEndpointsForIntent, getIntentByMetric, getAvailableIntents, } from "./intent-routing.generated.js";
|
|
12
|
+
import { ANALYSIS_WORKFLOWS, getLayersForDepth, getWorkflowEndpoints, getEndpointsForDepth, matchWorkflow, getAvailableWorkflows, } from "./workflows.generated.js";
|
|
13
|
+
import { SKILL_PROMPTS, getSkillPrompt, getSkillMetadata, getAvailableSkills, toMcpPrompt, } from "./skill-prompts.generated.js";
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Unified Data Export
|
|
16
|
+
// =============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* All CryptoQuant data in one object
|
|
19
|
+
*/
|
|
20
|
+
export const CRYPTOQUANT_DATA = {
|
|
21
|
+
// Metric definitions and scoring
|
|
22
|
+
metrics: METRIC_DEFINITIONS,
|
|
23
|
+
scoring: SCORING_RULES,
|
|
24
|
+
// Thresholds for interpretation
|
|
25
|
+
thresholds: {
|
|
26
|
+
market: MARKET_THRESHOLDS,
|
|
27
|
+
whale: WHALE_THRESHOLDS,
|
|
28
|
+
cycle: CYCLE_PHASES,
|
|
29
|
+
signal: SIGNAL_LEGEND,
|
|
30
|
+
},
|
|
31
|
+
// Intent routing (user question -> metric mapping)
|
|
32
|
+
intents: INTENT_ROUTING,
|
|
33
|
+
// Analysis workflows (multi-metric analysis)
|
|
34
|
+
workflows: ANALYSIS_WORKFLOWS,
|
|
35
|
+
// Skill prompts (slash commands)
|
|
36
|
+
skills: SKILL_PROMPTS,
|
|
37
|
+
// System prompts
|
|
38
|
+
prompts: {
|
|
39
|
+
interpretation: INTERPRETATION_SYSTEM_PROMPT,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// Unified Helper Functions
|
|
44
|
+
// =============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Helper functions for working with CryptoQuant data
|
|
47
|
+
*/
|
|
48
|
+
export const CryptoQuantHelpers = {
|
|
49
|
+
// Metrics
|
|
50
|
+
calculateScore,
|
|
51
|
+
calculateTradingSignal,
|
|
52
|
+
getMetricSignal,
|
|
53
|
+
getMetricDefinition,
|
|
54
|
+
getAvailableMetrics,
|
|
55
|
+
// Intents
|
|
56
|
+
matchIntent,
|
|
57
|
+
getEndpointsForIntent,
|
|
58
|
+
getIntentByMetric,
|
|
59
|
+
getAvailableIntents,
|
|
60
|
+
// Workflows
|
|
61
|
+
getLayersForDepth,
|
|
62
|
+
getWorkflowEndpoints,
|
|
63
|
+
getEndpointsForDepth,
|
|
64
|
+
matchWorkflow,
|
|
65
|
+
getAvailableWorkflows,
|
|
66
|
+
// Skills
|
|
67
|
+
getSkillPrompt,
|
|
68
|
+
getSkillMetadata,
|
|
69
|
+
getAvailableSkills,
|
|
70
|
+
toMcpPrompt,
|
|
71
|
+
};
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// Convenience Re-exports (for backward compatibility)
|
|
74
|
+
// =============================================================================
|
|
75
|
+
// Most commonly used - direct access without going through CRYPTOQUANT_DATA
|
|
76
|
+
export { METRIC_DEFINITIONS, SCORING_RULES, INTERPRETATION_SYSTEM_PROMPT, INTENT_ROUTING, ANALYSIS_WORKFLOWS, SKILL_PROMPTS, };
|
|
77
|
+
// Commonly used functions - direct access
|
|
78
|
+
export { calculateScore, calculateTradingSignal, getMetricSignal, getMetricDefinition, getAvailableMetrics, matchIntent, matchWorkflow, getSkillPrompt, };
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gFAAgF;AAChF,4BAA4B;AAC5B,gFAAgF;AAEhF,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,4BAA4B,EAC5B,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AAQrC,OAAO,EACL,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AAMvC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,GACZ,MAAM,8BAA8B,CAAC;AAGtC,gFAAgF;AAChF,sBAAsB;AACtB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,iCAAiC;IACjC,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EAAE,aAAa;IAEtB,gCAAgC;IAChC,UAAU,EAAE;QACV,MAAM,EAAE,iBAAiB;QACzB,KAAK,EAAE,gBAAgB;QACvB,KAAK,EAAE,YAAY;QACnB,MAAM,EAAE,aAAa;KACtB;IAED,mDAAmD;IACnD,OAAO,EAAE,cAAc;IAEvB,6CAA6C;IAC7C,SAAS,EAAE,kBAAkB;IAE7B,iCAAiC;IACjC,MAAM,EAAE,aAAa;IAErB,iBAAiB;IACjB,OAAO,EAAE;QACP,cAAc,EAAE,4BAA4B;KAC7C;CACO,CAAC;AAEX,gFAAgF;AAChF,2BAA2B;AAC3B,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,UAAU;IACV,cAAc;IACd,sBAAsB;IACtB,eAAe;IACf,mBAAmB;IACnB,mBAAmB;IAEnB,UAAU;IACV,WAAW;IACX,qBAAqB;IACrB,iBAAiB;IACjB,mBAAmB;IAEnB,YAAY;IACZ,iBAAiB;IACjB,oBAAoB;IACpB,oBAAoB;IACpB,aAAa;IACb,qBAAqB;IAErB,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;CACH,CAAC;AAwBX,gFAAgF;AAChF,sDAAsD;AACtD,gFAAgF;AAEhF,4EAA4E;AAC5E,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,4BAA4B,EAC5B,cAAc,EACd,kBAAkB,EAClB,aAAa,GACd,CAAC;AAEF,0CAA0C;AAC1C,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,cAAc,GACf,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY
|
|
3
|
+
*
|
|
4
|
+
* Generated by: npm run sync-skills
|
|
5
|
+
* Source: skills/crypto/INTENT_MAP.md
|
|
6
|
+
*/
|
|
7
|
+
export interface AdditionalMetric {
|
|
8
|
+
metric: string;
|
|
9
|
+
endpoint: string;
|
|
10
|
+
plan: string;
|
|
11
|
+
useCase: string;
|
|
12
|
+
}
|
|
13
|
+
export interface IntentConfig {
|
|
14
|
+
id: string;
|
|
15
|
+
triggers: string[];
|
|
16
|
+
primaryMetric: string;
|
|
17
|
+
endpoint: string;
|
|
18
|
+
plan: string;
|
|
19
|
+
definition?: string;
|
|
20
|
+
interpretation?: string;
|
|
21
|
+
additionalMetrics: AdditionalMetric[];
|
|
22
|
+
}
|
|
23
|
+
export declare const INTENT_ROUTING: Record<string, IntentConfig>;
|
|
24
|
+
/**
|
|
25
|
+
* Match user question to intent based on trigger keywords
|
|
26
|
+
*/
|
|
27
|
+
export declare function matchIntent(question: string): IntentConfig | null;
|
|
28
|
+
/**
|
|
29
|
+
* Get all endpoints needed for an intent (primary + additional)
|
|
30
|
+
*/
|
|
31
|
+
export declare function getEndpointsForIntent(intentId: string): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Get intent by primary metric ID
|
|
34
|
+
*/
|
|
35
|
+
export declare function getIntentByMetric(metricId: string): IntentConfig | null;
|
|
36
|
+
/**
|
|
37
|
+
* Get all available intent IDs
|
|
38
|
+
*/
|
|
39
|
+
export declare function getAvailableIntents(): string[];
|
|
40
|
+
//# sourceMappingURL=intent-routing.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-routing.generated.d.ts","sourceRoot":"","sources":["../../src/shared/intent-routing.generated.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAMD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA6cvD,CAAC;AAMF;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAWjE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAOvE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C"}
|