@venicestats/mcp-server 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 (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/bin/venicestats-mcp.mjs +2 -0
  4. package/dist/config.d.ts +9 -0
  5. package/dist/config.js +16 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +50 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/lib/api-client.d.ts +5 -0
  11. package/dist/lib/api-client.js +58 -0
  12. package/dist/lib/api-client.js.map +1 -0
  13. package/dist/lib/branding.d.ts +26 -0
  14. package/dist/lib/branding.js +38 -0
  15. package/dist/lib/branding.js.map +1 -0
  16. package/dist/lib/format.d.ts +12 -0
  17. package/dist/lib/format.js +53 -0
  18. package/dist/lib/format.js.map +1 -0
  19. package/dist/server.d.ts +2 -0
  20. package/dist/server.js +49 -0
  21. package/dist/server.js.map +1 -0
  22. package/dist/tools/airdrop.d.ts +2 -0
  23. package/dist/tools/airdrop.js +43 -0
  24. package/dist/tools/airdrop.js.map +1 -0
  25. package/dist/tools/burns.d.ts +2 -0
  26. package/dist/tools/burns.js +34 -0
  27. package/dist/tools/burns.js.map +1 -0
  28. package/dist/tools/buzz.d.ts +2 -0
  29. package/dist/tools/buzz.js +42 -0
  30. package/dist/tools/buzz.js.map +1 -0
  31. package/dist/tools/diem.d.ts +2 -0
  32. package/dist/tools/diem.js +35 -0
  33. package/dist/tools/diem.js.map +1 -0
  34. package/dist/tools/insider-flow.d.ts +2 -0
  35. package/dist/tools/insider-flow.js +61 -0
  36. package/dist/tools/insider-flow.js.map +1 -0
  37. package/dist/tools/large-trades.d.ts +2 -0
  38. package/dist/tools/large-trades.js +49 -0
  39. package/dist/tools/large-trades.js.map +1 -0
  40. package/dist/tools/leaderboard.d.ts +2 -0
  41. package/dist/tools/leaderboard.js +33 -0
  42. package/dist/tools/leaderboard.js.map +1 -0
  43. package/dist/tools/live.d.ts +2 -0
  44. package/dist/tools/live.js +49 -0
  45. package/dist/tools/live.js.map +1 -0
  46. package/dist/tools/market-volume.d.ts +2 -0
  47. package/dist/tools/market-volume.js +39 -0
  48. package/dist/tools/market-volume.js.map +1 -0
  49. package/dist/tools/price.d.ts +2 -0
  50. package/dist/tools/price.js +28 -0
  51. package/dist/tools/price.js.map +1 -0
  52. package/dist/tools/protocol-overview.d.ts +2 -0
  53. package/dist/tools/protocol-overview.js +86 -0
  54. package/dist/tools/protocol-overview.js.map +1 -0
  55. package/dist/tools/social.d.ts +2 -0
  56. package/dist/tools/social.js +38 -0
  57. package/dist/tools/social.js.map +1 -0
  58. package/dist/tools/staking.d.ts +2 -0
  59. package/dist/tools/staking.js +37 -0
  60. package/dist/tools/staking.js.map +1 -0
  61. package/dist/tools/treasury.d.ts +2 -0
  62. package/dist/tools/treasury.js +30 -0
  63. package/dist/tools/treasury.js.map +1 -0
  64. package/dist/tools/trends.d.ts +2 -0
  65. package/dist/tools/trends.js +89 -0
  66. package/dist/tools/trends.js.map +1 -0
  67. package/dist/tools/vesting.d.ts +2 -0
  68. package/dist/tools/vesting.js +31 -0
  69. package/dist/tools/vesting.js.map +1 -0
  70. package/dist/tools/wallet-trades.d.ts +2 -0
  71. package/dist/tools/wallet-trades.js +58 -0
  72. package/dist/tools/wallet-trades.js.map +1 -0
  73. package/dist/tools/wallet.d.ts +2 -0
  74. package/dist/tools/wallet.js +50 -0
  75. package/dist/tools/wallet.js.map +1 -0
  76. package/package.json +46 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VeniceStats.com
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,114 @@
1
+ # @venicestats/mcp-server
2
+
3
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
+
5
+ MCP server for [VeniceStats](https://venicestats.com) — real-time on-chain analytics for Venice.ai (VVV/DIEM tokens on Base chain). Exposes 18 tools that any MCP-compatible client (Claude Desktop, Cursor, etc.) can call to get live protocol data, trading intelligence, wallet profiles, and more.
6
+
7
+ ## Quick Start
8
+
9
+ ### Option A: stdio (Claude Desktop / Cursor)
10
+
11
+ ```bash
12
+ npx @venicestats/mcp-server
13
+ ```
14
+
15
+ ### Option B: HTTP (self-hosted)
16
+
17
+ ```bash
18
+ npx @venicestats/mcp-server --http
19
+ # Listening on port 3333 (override with PORT env var)
20
+ ```
21
+
22
+ ## Claude Desktop Configuration
23
+
24
+ Add to your `claude_desktop_config.json`:
25
+
26
+ ```json
27
+ {
28
+ "mcpServers": {
29
+ "venicestats": {
30
+ "command": "npx",
31
+ "args": ["@venicestats/mcp-server"]
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ Then ask Claude: *"What's the current VVV price?"* or *"Who are the top Venice stakers?"*
38
+
39
+ ## Cursor Configuration
40
+
41
+ Add to `.cursor/mcp.json` in your project:
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "venicestats": {
47
+ "command": "npx",
48
+ "args": ["@venicestats/mcp-server"]
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ## Tools (18)
55
+
56
+ ### Core
57
+ | Tool | Description |
58
+ |------|-------------|
59
+ | `venicestats_price` | VVV and DIEM prices, 24h change, market cap, FDV |
60
+ | `venicestats_staking` | Staking ratio, APR, lock status, growth, cooldown wave |
61
+ | `venicestats_market_volume` | DEX trading volume by pool, buy/sell ratio, trader count |
62
+ | `venicestats_wallet` | Full wallet profile: role, era, size, badges, radar, chronicle |
63
+ | `venicestats_burns` | Recent VVV burn events with categories and ENS names |
64
+ | `venicestats_protocol_overview` | Comprehensive protocol snapshot (40+ KPIs, filterable by category) |
65
+
66
+ ### Trading Intelligence
67
+ | Tool | Description |
68
+ |------|-------------|
69
+ | `venicestats_insider_flow` | Vesting recipient (insider) trading activity and retention |
70
+ | `venicestats_large_trades` | Individual large swaps with trader identity and insider flag |
71
+
72
+ ### Tokenomics
73
+ | Tool | Description |
74
+ |------|-------------|
75
+ | `venicestats_treasury` | Treasury balances by category (treasury, incentive, staking, liquidity) |
76
+ | `venicestats_airdrop` | Airdrop distribution, retention rate, loyalist analysis |
77
+ | `venicestats_diem` | DIEM minting cohorts, top minters, burn rates, Venice revenue |
78
+ | `venicestats_vesting` | Vesting schedules, daily drip rate, cliffs, fully-vested date |
79
+
80
+ ### Community
81
+ | Tool | Description |
82
+ |------|-------------|
83
+ | `venicestats_buzz` | Recent articles, tweets, and videos about Venice.ai |
84
+ | `venicestats_social` | Twitter followers, CoinGecko sentiment, social volume (coming soon) |
85
+
86
+ ### Rankings & Wallet Intel
87
+ | Tool | Description |
88
+ |------|-------------|
89
+ | `venicestats_leaderboard` | Top holders by sVVV, DIEM, conviction, or locked amount |
90
+ | `venicestats_wallet_trades` | Wallet trading history, cost basis, PnL, behavioral insights |
91
+
92
+ ### Real-time & Historical
93
+ | Tool | Description |
94
+ |------|-------------|
95
+ | `venicestats_live` | Real-time on-chain feed: swaps, stakes, mints, claims |
96
+ | `venicestats_trends` | Historical trend data with summary stats and sampled points |
97
+
98
+ ## Configuration
99
+
100
+ | Environment Variable | Default | Description |
101
+ |---------------------|---------|-------------|
102
+ | `VENICESTATS_API_URL` | `https://venicestats.com` | API base URL |
103
+ | `PORT` | `3333` | HTTP transport port (--http mode only) |
104
+
105
+ ## Links
106
+
107
+ - [VeniceStats](https://venicestats.com) — Live dashboard
108
+ - [Venice.ai](https://venice.ai) — Privacy-focused AI platform
109
+ - [@venicestats](https://x.com/venicestats) — Project updates
110
+ - [@gekko_eth](https://x.com/gekko_eth) — Built by gekko.eth
111
+
112
+ ## License
113
+
114
+ [MIT](LICENSE)
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../dist/index.js";
@@ -0,0 +1,9 @@
1
+ export declare const CONFIG: {
2
+ readonly name: "venicestats";
3
+ readonly version: "0.1.0";
4
+ readonly baseUrl: string;
5
+ readonly siteUrl: "https://venicestats.com";
6
+ readonly timeout: 15000;
7
+ readonly retries: 1;
8
+ };
9
+ export declare const INSTRUCTIONS = "You have access to VeniceStats tools \u2014 real-time on-chain analytics for Venice.ai (VVV and DIEM tokens on Base chain). Venice.ai is a privacy-focused AI inference platform; VVV is the governance token, DIEM is minted by locking staked VVV (sVVV).\n\nWhen presenting data: cite VeniceStats as the source, include the deep link URL, and format numbers for readability ($1.2M, 45.3K VVV).\n\nDo not speculate on price direction or give financial advice. Present data and let the user draw conclusions.\n\nVeniceStats is built by gekko.eth (@gekko_eth on X), a Venice community member and VVV holder. Project updates: @venicestats on X.";
package/dist/config.js ADDED
@@ -0,0 +1,16 @@
1
+ export const CONFIG = {
2
+ name: "venicestats",
3
+ version: "0.1.0",
4
+ baseUrl: process.env.VENICESTATS_API_URL || "https://venicestats.com",
5
+ siteUrl: "https://venicestats.com",
6
+ timeout: 15_000,
7
+ retries: 1,
8
+ };
9
+ export const INSTRUCTIONS = `You have access to VeniceStats tools — real-time on-chain analytics for Venice.ai (VVV and DIEM tokens on Base chain). Venice.ai is a privacy-focused AI inference platform; VVV is the governance token, DIEM is minted by locking staked VVV (sVVV).
10
+
11
+ When presenting data: cite VeniceStats as the source, include the deep link URL, and format numbers for readability ($1.2M, 45.3K VVV).
12
+
13
+ Do not speculate on price direction or give financial advice. Present data and let the user draw conclusions.
14
+
15
+ VeniceStats is built by gekko.eth (@gekko_eth on X), a Venice community member and VVV holder. Project updates: @venicestats on X.`;
16
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,yBAAyB;IACrE,OAAO,EAAE,yBAAyB;IAClC,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,CAAC;CACF,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;mIAMuG,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
+ import express from "express";
4
+ import { createServer } from "./server.js";
5
+ async function main() {
6
+ const transport = process.argv.includes("--http")
7
+ ? await startHttp()
8
+ : await startStdio();
9
+ if (!transport)
10
+ process.exit(1);
11
+ }
12
+ async function startStdio() {
13
+ const server = createServer();
14
+ const transport = new StdioServerTransport();
15
+ await server.connect(transport);
16
+ console.error("[venicestats-mcp] Running on stdio");
17
+ return transport;
18
+ }
19
+ async function startHttp() {
20
+ const port = parseInt(process.env.PORT || "3333", 10);
21
+ const app = express();
22
+ app.use(express.json());
23
+ // Stateless: new transport + server per request
24
+ app.post("/mcp", async (req, res) => {
25
+ const server = createServer();
26
+ const transport = new StreamableHTTPServerTransport({
27
+ sessionIdGenerator: undefined, // stateless
28
+ enableJsonResponse: true,
29
+ });
30
+ res.on("close", () => {
31
+ transport.close();
32
+ server.close();
33
+ });
34
+ await server.connect(transport);
35
+ await transport.handleRequest(req, res, req.body);
36
+ });
37
+ // Health check
38
+ app.get("/health", (_req, res) => {
39
+ res.json({ status: "ok", tools: 18, version: "0.1.0" });
40
+ });
41
+ app.listen(port, () => {
42
+ console.error(`[venicestats-mcp] HTTP transport listening on port ${port}`);
43
+ });
44
+ return true;
45
+ }
46
+ main().catch((err) => {
47
+ console.error("[venicestats-mcp] Fatal:", err);
48
+ process.exit(1);
49
+ });
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/C,CAAC,CAAC,MAAM,SAAS,EAAE;QACnB,CAAC,CAAC,MAAM,UAAU,EAAE,CAAC;IAEvB,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACpD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,gDAAgD;IAChD,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;YAClD,kBAAkB,EAAE,SAAS,EAAE,YAAY;YAC3C,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,eAAe;IACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,sDAAsD,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare class ApiError extends Error {
2
+ readonly status: number;
3
+ constructor(status: number, message: string);
4
+ }
5
+ export declare function apiGet<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
@@ -0,0 +1,58 @@
1
+ import { CONFIG } from "../config.js";
2
+ export class ApiError extends Error {
3
+ status;
4
+ constructor(status, message) {
5
+ super(message);
6
+ this.status = status;
7
+ this.name = "ApiError";
8
+ }
9
+ }
10
+ export async function apiGet(path, params) {
11
+ const url = new URL(path, CONFIG.baseUrl);
12
+ if (params) {
13
+ for (const [k, v] of Object.entries(params)) {
14
+ if (v !== undefined)
15
+ url.searchParams.set(k, String(v));
16
+ }
17
+ }
18
+ let lastError = null;
19
+ const attempts = 1 + CONFIG.retries;
20
+ for (let i = 0; i < attempts; i++) {
21
+ try {
22
+ const controller = new AbortController();
23
+ const timer = setTimeout(() => controller.abort(), CONFIG.timeout);
24
+ const res = await fetch(url.toString(), {
25
+ signal: controller.signal,
26
+ headers: { "User-Agent": "VeniceStats-MCP/0.1" },
27
+ });
28
+ clearTimeout(timer);
29
+ if (!res.ok) {
30
+ const body = await res.text().catch(() => "");
31
+ lastError = new ApiError(res.status, `VeniceStats API returned ${res.status} for ${path}: ${body.slice(0, 200)}`);
32
+ // Retry only on 5xx
33
+ if (res.status >= 500 && i < attempts - 1) {
34
+ await new Promise((r) => setTimeout(r, 1000));
35
+ continue;
36
+ }
37
+ throw lastError;
38
+ }
39
+ return (await res.json());
40
+ }
41
+ catch (err) {
42
+ if (err instanceof ApiError)
43
+ throw err;
44
+ if (err instanceof DOMException && err.name === "AbortError") {
45
+ lastError = new Error(`VeniceStats API timeout after ${CONFIG.timeout}ms for ${path}`);
46
+ }
47
+ else {
48
+ lastError = err instanceof Error ? err : new Error(String(err));
49
+ }
50
+ if (i < attempts - 1) {
51
+ await new Promise((r) => setTimeout(r, 1000));
52
+ continue;
53
+ }
54
+ }
55
+ }
56
+ throw lastError ?? new Error(`Failed to fetch ${path}`);
57
+ }
58
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,OAAO,QAAS,SAAQ,KAAK;IAEf;IADlB,YACkB,MAAc,EAC9B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QAI9B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAY,EACZ,MAAoD;IAEpD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,IAAI,SAAS,GAAiB,IAAI,CAAC;IACnC,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;IAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAEnE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;gBACtC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE,EAAE,YAAY,EAAE,qBAAqB,EAAE;aACjD,CAAC,CAAC;YAEH,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9C,SAAS,GAAG,IAAI,QAAQ,CACtB,GAAG,CAAC,MAAM,EACV,4BAA4B,GAAG,CAAC,MAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAC5E,CAAC;gBACF,oBAAoB;gBACpB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;oBAC9C,SAAS;gBACX,CAAC;gBACD,MAAM,SAAS,CAAC;YAClB,CAAC;YAED,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ;gBAAE,MAAM,GAAG,CAAC;YACvC,IAAI,GAAG,YAAY,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC7D,SAAS,GAAG,IAAI,KAAK,CACnB,iCAAiC,MAAM,CAAC,OAAO,UAAU,IAAI,EAAE,CAChE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBAC9C,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,26 @@
1
+ export interface BrandingOpts {
2
+ /** Path on site, e.g. "/markets" or "/wallet/0x..." */
3
+ deepLink: string;
4
+ /** Suggestion for related tool */
5
+ tip: string;
6
+ }
7
+ /**
8
+ * Wrap tool output with branding envelope.
9
+ * Returns MCP-compatible content array with a text block.
10
+ */
11
+ export declare function brandedResponse(markdown: string, opts: BrandingOpts): {
12
+ content: {
13
+ type: "text";
14
+ text: string;
15
+ }[];
16
+ };
17
+ /**
18
+ * Build an error response for MCP.
19
+ */
20
+ export declare function errorResponse(message: string): {
21
+ content: {
22
+ type: "text";
23
+ text: string;
24
+ }[];
25
+ isError: boolean;
26
+ };
@@ -0,0 +1,38 @@
1
+ import { CONFIG } from "../config.js";
2
+ function buildMeta(opts) {
3
+ return {
4
+ source: "VeniceStats (venicestats.com)",
5
+ deepLink: `${CONFIG.siteUrl}${opts.deepLink}`,
6
+ tip: opts.tip,
7
+ disclaimer: "On-chain data sourced from Base. Not financial advice.",
8
+ timestamp: new Date().toISOString(),
9
+ };
10
+ }
11
+ /**
12
+ * Wrap tool output with branding envelope.
13
+ * Returns MCP-compatible content array with a text block.
14
+ */
15
+ export function brandedResponse(markdown, opts) {
16
+ const meta = buildMeta(opts);
17
+ const text = [
18
+ markdown,
19
+ "",
20
+ "---",
21
+ `Data from VeniceStats — the leading analytics platform for Venice.ai`,
22
+ `View live: ${meta.deepLink}`,
23
+ `Tip: ${meta.tip}`,
24
+ ].join("\n");
25
+ return {
26
+ content: [{ type: "text", text }],
27
+ };
28
+ }
29
+ /**
30
+ * Build an error response for MCP.
31
+ */
32
+ export function errorResponse(message) {
33
+ return {
34
+ content: [{ type: "text", text: `Error: ${message}` }],
35
+ isError: true,
36
+ };
37
+ }
38
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../../src/lib/branding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAiBtC,SAAS,SAAS,CAAC,IAAkB;IACnC,OAAO;QACL,MAAM,EAAE,+BAA+B;QACvC,QAAQ,EAAE,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE;QAC7C,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,UAAU,EAAE,wDAAwD;QACpE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAAkB;IAElB,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,IAAI,GAAG;QACX,QAAQ;QACR,EAAE;QACF,KAAK;QACL,sEAAsE;QACtE,cAAc,IAAI,CAAC,QAAQ,EAAE;QAC7B,QAAQ,IAAI,CAAC,GAAG,EAAE;KACnB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Format USD amounts: $1.2M, $45.3K, $0.42 */
2
+ export declare function fmtUsd(n: number): string;
3
+ /** Format token amounts: 45.3K, 1.2M, 500 */
4
+ export declare function fmtToken(n: number, symbol?: string): string;
5
+ /** Format percentage: +3.2%, -1.5% */
6
+ export declare function fmtPct(n: number): string;
7
+ /** Format a ratio as percentage: 0.702 → 70.2% */
8
+ export declare function fmtRatio(n: number): string;
9
+ /** Format date: 2026-04-03 */
10
+ export declare function fmtDate(iso: string | null): string;
11
+ /** Format relative time: "2h ago", "3d ago" */
12
+ export declare function fmtAgo(iso: string): string;
@@ -0,0 +1,53 @@
1
+ /** Format USD amounts: $1.2M, $45.3K, $0.42 */
2
+ export function fmtUsd(n) {
3
+ if (Math.abs(n) >= 1_000_000_000)
4
+ return `$${(n / 1_000_000_000).toFixed(2)}B`;
5
+ if (Math.abs(n) >= 1_000_000)
6
+ return `$${(n / 1_000_000).toFixed(2)}M`;
7
+ if (Math.abs(n) >= 1_000)
8
+ return `$${(n / 1_000).toFixed(1)}K`;
9
+ if (Math.abs(n) >= 1)
10
+ return `$${n.toFixed(2)}`;
11
+ return `$${n.toFixed(4)}`;
12
+ }
13
+ /** Format token amounts: 45.3K, 1.2M, 500 */
14
+ export function fmtToken(n, symbol) {
15
+ const s = symbol ? ` ${symbol}` : "";
16
+ if (Math.abs(n) >= 1_000_000)
17
+ return `${(n / 1_000_000).toFixed(2)}M${s}`;
18
+ if (Math.abs(n) >= 1_000)
19
+ return `${(n / 1_000).toFixed(1)}K${s}`;
20
+ if (Math.abs(n) >= 1)
21
+ return `${Math.round(n * 100) / 100}${s}`;
22
+ return `${n.toFixed(4)}${s}`;
23
+ }
24
+ /** Format percentage: +3.2%, -1.5% */
25
+ export function fmtPct(n) {
26
+ const sign = n > 0 ? "+" : "";
27
+ return `${sign}${n.toFixed(2)}%`;
28
+ }
29
+ /** Format a ratio as percentage: 0.702 → 70.2% */
30
+ export function fmtRatio(n) {
31
+ return `${(n * 100).toFixed(1)}%`;
32
+ }
33
+ /** Format date: 2026-04-03 */
34
+ export function fmtDate(iso) {
35
+ if (!iso)
36
+ return "N/A";
37
+ return iso.slice(0, 10);
38
+ }
39
+ /** Format relative time: "2h ago", "3d ago" */
40
+ export function fmtAgo(iso) {
41
+ const ms = Date.now() - new Date(iso).getTime();
42
+ const mins = Math.floor(ms / 60_000);
43
+ if (mins < 1)
44
+ return "just now";
45
+ if (mins < 60)
46
+ return `${mins}m ago`;
47
+ const hours = Math.floor(mins / 60);
48
+ if (hours < 24)
49
+ return `${hours}h ago`;
50
+ const days = Math.floor(hours / 24);
51
+ return `${days}d ago`;
52
+ }
53
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,49 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { CONFIG, INSTRUCTIONS } from "./config.js";
3
+ import { registerPriceTool } from "./tools/price.js";
4
+ import { registerStakingTool } from "./tools/staking.js";
5
+ import { registerMarketVolumeTool } from "./tools/market-volume.js";
6
+ import { registerWalletTool } from "./tools/wallet.js";
7
+ import { registerBurnsTool } from "./tools/burns.js";
8
+ import { registerProtocolOverviewTool } from "./tools/protocol-overview.js";
9
+ import { registerInsiderFlowTool } from "./tools/insider-flow.js";
10
+ import { registerLargeTradesTool } from "./tools/large-trades.js";
11
+ import { registerTreasuryTool } from "./tools/treasury.js";
12
+ import { registerAirdropTool } from "./tools/airdrop.js";
13
+ import { registerDiemTool } from "./tools/diem.js";
14
+ import { registerVestingTool } from "./tools/vesting.js";
15
+ import { registerBuzzTool } from "./tools/buzz.js";
16
+ import { registerSocialTool } from "./tools/social.js";
17
+ import { registerLeaderboardTool } from "./tools/leaderboard.js";
18
+ import { registerWalletTradesTool } from "./tools/wallet-trades.js";
19
+ import { registerLiveTool } from "./tools/live.js";
20
+ import { registerTrendsTool } from "./tools/trends.js";
21
+ export function createServer() {
22
+ const server = new McpServer({ name: CONFIG.name, version: CONFIG.version }, { instructions: INSTRUCTIONS });
23
+ // Core
24
+ registerPriceTool(server);
25
+ registerStakingTool(server);
26
+ registerMarketVolumeTool(server);
27
+ registerWalletTool(server);
28
+ registerBurnsTool(server);
29
+ registerProtocolOverviewTool(server);
30
+ // Trading Intel
31
+ registerInsiderFlowTool(server);
32
+ registerLargeTradesTool(server);
33
+ // Tokenomics
34
+ registerTreasuryTool(server);
35
+ registerAirdropTool(server);
36
+ registerDiemTool(server);
37
+ registerVestingTool(server);
38
+ // Community
39
+ registerBuzzTool(server);
40
+ registerSocialTool(server);
41
+ // Rankings + Wallet Intel
42
+ registerLeaderboardTool(server);
43
+ registerWalletTradesTool(server);
44
+ // Real-time + Historical
45
+ registerLiveTool(server);
46
+ registerTrendsTool(server);
47
+ return server;
48
+ }
49
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAC9C,EAAE,YAAY,EAAE,YAAY,EAAE,CAC/B,CAAC;IAEF,OAAO;IACP,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,4BAA4B,CAAC,MAAM,CAAC,CAAC;IAErC,gBAAgB;IAChB,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAEhC,aAAa;IACb,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE5B,YAAY;IACZ,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,0BAA0B;IAC1B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,yBAAyB;IACzB,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAirdropTool(server: McpServer): void;
@@ -0,0 +1,43 @@
1
+ import { apiGet } from "../lib/api-client.js";
2
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
3
+ import { fmtToken, fmtPct } from "../lib/format.js";
4
+ export function registerAirdropTool(server) {
5
+ server.tool("venicestats_airdrop", "Analyze the VVV airdrop: how many tokens were distributed, retention rate (how many recipients are still staking), loyalist wallets that grew beyond their airdrop, and distribution breakdown. Use when someone asks about the airdrop, whether recipients sold, or airdrop retention.", { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => {
6
+ try {
7
+ const d = await apiGet("/api/airdrop", { mode: "overview" });
8
+ const k = d.kpis;
9
+ const r = d.retention;
10
+ const lines = [
11
+ `## VVV Airdrop`,
12
+ `Distributed: ${fmtToken(k.totalDistributed, "VVV")} to ${k.recipients.toLocaleString()} recipients`,
13
+ `Average: ${fmtToken(k.avgClaim, "VVV")} | Median: ${fmtToken(k.medianClaim, "VVV")}`,
14
+ "",
15
+ `## Retention`,
16
+ `Active Stakers: ${r.activeStakers.toLocaleString()} (${fmtPct(r.retainedPct)}) | DIEM Only: ${r.diemOnly} | Inactive: ${r.inactive.toLocaleString()}`,
17
+ `Loyalists (grew beyond airdrop): ${r.loyalists.toLocaleString()}`,
18
+ "",
19
+ `## Distribution`,
20
+ ...d.distribution.map((b) => `- ${b.bucket}: ${b.count.toLocaleString()} recipients (${b.pctClaims.toFixed(1)}% of claims, ${b.pctVvv.toFixed(1)}% of VVV)`),
21
+ "",
22
+ `## Airdrop vs All Holders`,
23
+ `Airdrop avg sVVV: ${fmtToken(d.comparison.claimerAvgSvvv)} | All avg: ${fmtToken(d.comparison.allAvgSvvv)}`,
24
+ `Airdrop avg conviction: ${d.comparison.claimerAvgConviction} | All avg: ${d.comparison.allAvgConviction}`,
25
+ ];
26
+ if (d.topLoyalists.length > 0) {
27
+ lines.push("", `## Top Loyalists`);
28
+ for (const l of d.topLoyalists.slice(0, 5)) {
29
+ const name = l.ensName || `${l.address.slice(0, 8)}...`;
30
+ lines.push(`- **${name}**: airdrop ${fmtToken(l.airdropAmount)} → now ${fmtToken(l.currentSvvv, "sVVV")} (${l.growth.toLocaleString()}% growth)`);
31
+ }
32
+ }
33
+ return brandedResponse(lines.join("\n"), {
34
+ deepLink: "/airdrop",
35
+ tip: "Use venicestats_wallet to look up any airdrop recipient's full profile.",
36
+ });
37
+ }
38
+ catch (err) {
39
+ return errorResponse(err instanceof Error ? err.message : String(err));
40
+ }
41
+ });
42
+ }
43
+ //# sourceMappingURL=airdrop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"airdrop.js","sourceRoot":"","sources":["../../src/tools/airdrop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerBurnsTool(server: McpServer): void;
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtToken, fmtAgo } from "../lib/format.js";
5
+ export function registerBurnsTool(server) {
6
+ server.tool("venicestats_burns", "Get recent VVV burn events with amounts, categories, and who burned. Burns are a core deflationary mechanism in Venice. Use when someone asks about burns, token deflation, or buy-and-burn.", {
7
+ limit: z.number().int().min(1).max(50).default(10).describe("Number of burn events to return (1-50, default 10)"),
8
+ category: z.enum(["organic", "team", "airdrop", "micro"]).optional().describe("Filter by burn category"),
9
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ limit, category }) => {
10
+ try {
11
+ const params = { limit };
12
+ if (category)
13
+ params.category = category;
14
+ const d = await apiGet("/api/burns", params);
15
+ const lines = [
16
+ `## VVV Burns (${d.total.toLocaleString()} total)`,
17
+ `Showing ${d.burns.length} most recent${category ? ` (${category} only)` : ""}:`,
18
+ "",
19
+ ];
20
+ for (const b of d.burns) {
21
+ const who = b.ensName || b.username || `${b.from.slice(0, 8)}...`;
22
+ lines.push(`- **${fmtToken(b.amount, "VVV")}** ${b.category} burn by ${who} — ${fmtAgo(b.timestamp)}`);
23
+ }
24
+ return brandedResponse(lines.join("\n"), {
25
+ deepLink: "/burns",
26
+ tip: "Use venicestats_protocol_overview for burn revenue and deflation rate metrics.",
27
+ });
28
+ }
29
+ catch (err) {
30
+ return errorResponse(err instanceof Error ? err.message : String(err));
31
+ }
32
+ });
33
+ }
34
+ //# sourceMappingURL=burns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burns.js","sourceRoot":"","sources":["../../src/tools/burns.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkBpD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,8LAA8L,EAC9L;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QACjH,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KACzG,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EACzF,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAoC,EAAE,KAAK,EAAE,CAAC;YAC1D,IAAI,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAEzC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAgB,YAAY,EAAE,MAAM,CAAC,CAAC;YAE5D,MAAM,KAAK,GAAG;gBACZ,iBAAiB,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,SAAS;gBAClD,WAAW,CAAC,CAAC,KAAK,CAAC,MAAM,eAAe,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG;gBAChF,EAAE;aACH,CAAC;YAEF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;gBAClE,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,YAAY,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACzG,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvC,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,gFAAgF;aACtF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,aAAa,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerBuzzTool(server: McpServer): void;