@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
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtAgo } from "../lib/format.js";
5
+ export function registerBuzzTool(server) {
6
+ server.tool("venicestats_buzz", "Get recent articles, tweets, and videos about Venice.ai. A curated news feed of community content. Use when someone asks about Venice news, what people are saying, recent articles, or community discussion.", {
7
+ type: z.enum(["article", "video", "tweet"]).optional().describe("Filter by content type"),
8
+ limit: z.number().int().min(1).max(20).default(10).describe("Number of items to return (1-20, default 10)"),
9
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ type, limit }) => {
10
+ try {
11
+ const params = { limit };
12
+ if (type)
13
+ params.type = type;
14
+ const d = await apiGet("/api/buzz", params);
15
+ const typeLabel = type || "all";
16
+ const lines = [
17
+ `## Venice Buzz — ${typeLabel} (${d.total} total)`,
18
+ "",
19
+ ];
20
+ for (const item of d.items) {
21
+ const source = item.sourceName || item.authorHandle || "Unknown";
22
+ const engagement = [
23
+ item.likeCount ? `${item.likeCount} likes` : null,
24
+ item.retweetCount ? `${item.retweetCount} RTs` : null,
25
+ ].filter(Boolean).join(", ");
26
+ lines.push(`### ${item.title}`);
27
+ lines.push(`${item.type} by ${source} — ${fmtAgo(item.publishedAt)}${engagement ? ` (${engagement})` : ""}`);
28
+ if (item.summary)
29
+ lines.push(item.summary);
30
+ lines.push(`[Read more](${item.url})`, "");
31
+ }
32
+ return brandedResponse(lines.join("\n"), {
33
+ deepLink: "/buzz",
34
+ tip: "Use venicestats_social for quantitative sentiment metrics (Twitter followers, CoinGecko sentiment).",
35
+ });
36
+ }
37
+ catch (err) {
38
+ return errorResponse(err instanceof Error ? err.message : String(err));
39
+ }
40
+ });
41
+ }
42
+ //# sourceMappingURL=buzz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buzz.js","sourceRoot":"","sources":["../../src/tools/buzz.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 registerDiemTool(server: McpServer): void;
@@ -0,0 +1,35 @@
1
+ import { apiGet } from "../lib/api-client.js";
2
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
3
+ import { fmtToken, fmtUsd } from "../lib/format.js";
4
+ export function registerDiemTool(server) {
5
+ server.tool("venicestats_diem", "Analyze DIEM token minting: cohort breakdown (Genesis to Current), top minters with burn rates, total locked sVVV, Venice revenue, and current mint rate. DIEM is minted by locking staked VVV (sVVV). Use when someone asks about DIEM minting, cohorts, burn rate, or who the biggest DIEM minters are.", { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => {
6
+ try {
7
+ const d = await apiGet("/api/diem-analytics");
8
+ const lines = [
9
+ `## DIEM Minting Overview`,
10
+ `Current Mint Rate: ${Math.round(d.currentMintRate)} sVVV per DIEM`,
11
+ `Total Locked: ${fmtToken(d.totalLockedSvvv, "sVVV")}`,
12
+ `Venice Revenue (20% haircut): ${fmtUsd(d.veniceRevenue20Pct)}/year`,
13
+ "",
14
+ `## Cohorts`,
15
+ ];
16
+ for (const c of d.cohorts) {
17
+ lines.push(`- **${c.name}**: ${c.walletCount} wallets, ${fmtToken(c.totalDiemMinted, "DIEM")} minted, avg burn rate ${Math.round(c.avgBurnRate)} sVVV/DIEM, ${Math.round(c.stillLockedPct * 100)}% still locked`);
18
+ }
19
+ lines.push("", `## Top 10 Minters`);
20
+ for (const m of d.topMinters.slice(0, 10)) {
21
+ const name = m.ensName || `${m.address.slice(0, 8)}...`;
22
+ const inference = m.inferencePerDay > 0 ? ` | $${Math.round(m.inferencePerDay)}/day inference` : "";
23
+ lines.push(`- **${name}** (${m.badge}): ${fmtToken(m.outstandingDiem, "DIEM")} outstanding, ${fmtToken(m.svvvLocked, "sVVV")} locked, rate ${Math.round(m.burnRate)}${inference}`);
24
+ }
25
+ return brandedResponse(lines.join("\n"), {
26
+ deepLink: "/diem",
27
+ tip: "Use venicestats_protocol_overview with category='diem' for DIEM price and supply metrics.",
28
+ });
29
+ }
30
+ catch (err) {
31
+ return errorResponse(err instanceof Error ? err.message : String(err));
32
+ }
33
+ });
34
+ }
35
+ //# sourceMappingURL=diem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diem.js","sourceRoot":"","sources":["../../src/tools/diem.ts"],"names":[],"mappings":"AACA,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;AA4BpD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,2SAA2S,EAC3S,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EACzF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAe,qBAAqB,CAAC,CAAC;YAE5D,MAAM,KAAK,GAAG;gBACZ,0BAA0B;gBAC1B,sBAAsB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,gBAAgB;gBACnE,iBAAiB,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE;gBACtD,iCAAiC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO;gBACpE,EAAE;gBACF,YAAY;aACb,CAAC;YAEF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,aAAa,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,MAAM,CAAC,0BAA0B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;YACpN,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;YACpC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;gBACxD,MAAM,SAAS,GAAG,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpG,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,KAAK,MAAM,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,MAAM,CAAC,iBAAiB,QAAQ,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,iBAAiB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC;YACrL,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvC,QAAQ,EAAE,OAAO;gBACjB,GAAG,EAAE,2FAA2F;aACjG,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 registerInsiderFlowTool(server: McpServer): void;
@@ -0,0 +1,61 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtToken, fmtPct } from "../lib/format.js";
5
+ export function registerInsiderFlowTool(server) {
6
+ server.tool("venicestats_insider_flow", "Analyze vesting recipient (insider) trading activity: are insiders buying or selling? Shows net flow, sell pressure trend, retention rate, and top recipients by behavior. Use when someone asks about insider selling, vesting recipient activity, or sell pressure from team/investors.", {
7
+ mode: z.enum(["overview", "recipients"]).default("overview").describe("'overview' for KPIs and trends, 'recipients' for per-wallet breakdown"),
8
+ limit: z.number().int().min(1).max(50).default(10).describe("Number of recipients to return (recipients mode only, default 10)"),
9
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ mode, limit }) => {
10
+ try {
11
+ if (mode === "overview") {
12
+ const d = await apiGet("/api/insider-flow", { mode: "overview" });
13
+ const k = d.kpis;
14
+ const flowDir = k.netFlow30d < 0 ? "net selling" : "net buying";
15
+ const flowChange = k.prevNetFlow30d !== 0
16
+ ? ((k.netFlow30d - k.prevNetFlow30d) / Math.abs(k.prevNetFlow30d)) * 100
17
+ : 0;
18
+ const lines = [
19
+ `## Insider Flow (30d)`,
20
+ `Net Flow: ${fmtToken(k.netFlow30d, "VVV")} (${flowDir}, ${fmtPct(flowChange)} vs prev 30d)`,
21
+ `Sell Volume: ${fmtToken(k.sellVolume30d, "VVV")} | Buy Volume: ${fmtToken(k.buyVolume30d, "VVV")}`,
22
+ `Sell Pressure: **${k.sellPressure}** (${k.sellTrendPct}% sell ratio)`,
23
+ "",
24
+ `## Retention`,
25
+ `Total Claimed: ${fmtToken(k.totalClaimed, "VVV")} | Currently Held: ${fmtToken(k.totalHeld, "VVV")}`,
26
+ `Retention Rate: ${k.retentionRate}%`,
27
+ "",
28
+ `## Activity`,
29
+ `Active Traders: ${k.activeTraders7d} (7d) / ${k.activeTraders30d} (30d)`,
30
+ `Total Trades (30d): ${k.totalTrades30d}`,
31
+ ];
32
+ return brandedResponse(lines.join("\n"), {
33
+ deepLink: "/vesting",
34
+ tip: "Use venicestats_insider_flow with mode='recipients' for per-wallet breakdown, or venicestats_vesting for unlock schedules.",
35
+ });
36
+ }
37
+ else {
38
+ const d = await apiGet("/api/insider-flow", { mode: "recipients" });
39
+ const top = d.recipients.slice(0, limit);
40
+ const lines = [
41
+ `## Top ${top.length} Insider Recipients`,
42
+ "",
43
+ ];
44
+ for (const r of top) {
45
+ const name = r.name || `${r.address.slice(0, 8)}...`;
46
+ const netFlow = r.buyVolume - r.sellVolume;
47
+ const netLabel = netFlow >= 0 ? "net buyer" : "net seller";
48
+ lines.push(`- **${name}** — ${r.behavior} | Claimed: ${fmtToken(r.claimed, "VVV")} | Sold: ${fmtToken(r.sellVolume)} | Retention: ${r.retention}% (${netLabel})`);
49
+ }
50
+ return brandedResponse(lines.join("\n"), {
51
+ deepLink: "/vesting",
52
+ tip: "Use venicestats_wallet to see full identity for any of these addresses.",
53
+ });
54
+ }
55
+ }
56
+ catch (err) {
57
+ return errorResponse(err instanceof Error ? err.message : String(err));
58
+ }
59
+ });
60
+ }
61
+ //# sourceMappingURL=insider-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insider-flow.js","sourceRoot":"","sources":["../../src/tools/insider-flow.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 registerLargeTradesTool(server: McpServer): void;
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtUsd, fmtToken, fmtAgo } from "../lib/format.js";
5
+ export function registerLargeTradesTool(server) {
6
+ server.tool("venicestats_large_trades", "Get individual large trades (swaps) for VVV or DIEM with trader identity, pool, direction, and insider flag. Use when someone asks about whale trades, big buys/sells, or where buy/sell pressure is coming from.", {
7
+ token: z.enum(["VVV", "DIEM"]).default("VVV").describe("Token to filter trades for"),
8
+ period: z.enum(["24h", "7d", "30d", "90d"]).default("7d").describe("Lookback period"),
9
+ direction: z.enum(["buy", "sell", "all"]).default("all").describe("Filter by trade direction"),
10
+ minVolume: z.number().min(0).default(1000).describe("Minimum trade volume in USD (default $1000)"),
11
+ limit: z.number().int().min(1).max(20).default(10).describe("Number of trades to return (1-20, default 10)"),
12
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ token, period, direction, minVolume, limit }) => {
13
+ try {
14
+ const d = await apiGet("/api/markets/large-swaps", {
15
+ token,
16
+ period,
17
+ direction: direction === "all" ? undefined : direction,
18
+ minVolume,
19
+ limit,
20
+ sort: "volume",
21
+ order: "desc",
22
+ });
23
+ const lines = [
24
+ `## Large ${token} Trades — ${period} (${d.pagination.total.toLocaleString()} total above ${fmtUsd(minVolume)})`,
25
+ "",
26
+ ];
27
+ if (d.swaps.length === 0) {
28
+ lines.push("No trades found matching the criteria.");
29
+ }
30
+ else {
31
+ for (const s of d.swaps) {
32
+ const dir = s.direction === "buy" ? "🟢 BUY" : "🔴 SELL";
33
+ const name = s.traderName || `${s.trader.slice(0, 8)}...`;
34
+ const insider = s.isVesting ? " [INSIDER]" : "";
35
+ const price = s.effectivePrice ? ` @ $${s.effectivePrice.toFixed(2)}` : "";
36
+ lines.push(`- ${dir} ${fmtUsd(s.volumeUsd)} (${fmtToken(s.tokenAmount, s.tokenLabel)}${price}) via ${s.poolName} (${s.dex}) by ${name}${insider} — ${fmtAgo(s.timestamp)}`);
37
+ }
38
+ }
39
+ return brandedResponse(lines.join("\n"), {
40
+ deepLink: `/markets?token=${token}&period=${period}`,
41
+ tip: "Use venicestats_wallet to look up any trader's full profile, or venicestats_insider_flow for aggregate insider activity.",
42
+ });
43
+ }
44
+ catch (err) {
45
+ return errorResponse(err instanceof Error ? err.message : String(err));
46
+ }
47
+ });
48
+ }
49
+ //# sourceMappingURL=large-trades.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"large-trades.js","sourceRoot":"","sources":["../../src/tools/large-trades.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 registerLeaderboardTool(server: McpServer): void;
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtToken } from "../lib/format.js";
5
+ export function registerLeaderboardTool(server) {
6
+ server.tool("venicestats_leaderboard", "Get the top VVV holders ranked by sVVV balance, DIEM staked, conviction score, or locked amount. Use when someone asks who the biggest holders/stakers are, top wallets, or leaderboard rankings.", {
7
+ sort: z.enum(["svvv", "diem", "conviction", "locked"]).default("svvv").describe("Sort by: svvv (staked balance), diem (DIEM staked), conviction (conviction score), locked (locked sVVV)"),
8
+ limit: z.number().int().min(1).max(25).default(10).describe("Number of holders to return (1-25, default 10)"),
9
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ sort, limit }) => {
10
+ try {
11
+ const d = await apiGet("/api/holders", { sort, limit });
12
+ const sortLabel = { svvv: "sVVV Balance", diem: "DIEM Staked", conviction: "Conviction Score", locked: "Locked sVVV" }[sort];
13
+ const lines = [
14
+ `## Venice Leaderboard — Top ${d.holders.length} by ${sortLabel}`,
15
+ `(${d.totalHolders.toLocaleString()} total holders)`,
16
+ "",
17
+ ];
18
+ for (const h of d.holders) {
19
+ const name = h.ensName || h.username || `${h.address.slice(0, 8)}...`;
20
+ const lockPct = h.svvvBalance > 0 ? Math.round((h.svvvLocked / h.svvvBalance) * 100) : 0;
21
+ lines.push(`${h.rank}. **${name}** — ${fmtToken(h.svvvBalance, "sVVV")} (${lockPct}% locked) | DIEM: ${fmtToken(h.diemStaked)} staked | Conviction: ${h.convictionScore.toLocaleString()}`);
22
+ }
23
+ return brandedResponse(lines.join("\n"), {
24
+ deepLink: "/venetians",
25
+ tip: "Use venicestats_wallet to see the full profile of any holder.",
26
+ });
27
+ }
28
+ catch (err) {
29
+ return errorResponse(err instanceof Error ? err.message : String(err));
30
+ }
31
+ });
32
+ }
33
+ //# sourceMappingURL=leaderboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leaderboard.js","sourceRoot":"","sources":["../../src/tools/leaderboard.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,kBAAkB,CAAC;AAoB5C,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,mMAAmM,EACnM;QACE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,yGAAyG,CAAC;QAC1L,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,gDAAgD,CAAC;KAC9G,EACD,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EACzF,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAkB,cAAc,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAEzE,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC;YAE7H,MAAM,KAAK,GAAG;gBACZ,+BAA+B,CAAC,CAAC,OAAO,CAAC,MAAM,OAAO,SAAS,EAAE;gBACjE,IAAI,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,iBAAiB;gBACpD,EAAE;aACH,CAAC;YAEF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;gBACtE,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzF,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,CAAC,IAAI,OAAO,IAAI,QAAQ,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,KAAK,OAAO,qBAAqB,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,CAChL,CAAC;YACJ,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvC,QAAQ,EAAE,YAAY;gBACtB,GAAG,EAAE,+DAA+D;aACrE,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 registerLiveTool(server: McpServer): void;
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtToken, fmtUsd, fmtPct, fmtAgo } from "../lib/format.js";
5
+ const TYPE_LABELS = {
6
+ buy: "🟢 BUY VVV",
7
+ sell: "🔴 SELL VVV",
8
+ buy_diem: "🟢 BUY DIEM",
9
+ sell_diem: "🔴 SELL DIEM",
10
+ stake: "📥 STAKE",
11
+ unstake: "📤 UNSTAKE",
12
+ claim: "🎁 CLAIM REWARDS",
13
+ finalize: "✅ FINALIZE UNSTAKE",
14
+ mint: "🔵 MINT DIEM",
15
+ burn: "🔥 BURN",
16
+ };
17
+ export function registerLiveTool(server) {
18
+ server.tool("venicestats_live", "Get a real-time feed of on-chain activity: swaps (buy/sell), staking events (stake, unstake, claim, finalize), DIEM events (mint, burn, stake), and vesting claims. Shows what is happening RIGHT NOW on Venice. Use when someone asks what's happening today, recent activity, or real-time events.", {
19
+ limit: z.number().int().min(1).max(50).default(20).describe("Number of events to return (1-50, default 20)"),
20
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ limit }) => {
21
+ try {
22
+ const d = await apiGet("/api/live", { limit });
23
+ const p = d.prices;
24
+ const lines = [
25
+ `## Live Feed (${d.events.length} events)`,
26
+ `VVV: ${fmtUsd(p.vvv)} (${fmtPct(p.vvvChange24h)}) | 24h Vol: ${fmtUsd(p.vvvVolume24h)}`,
27
+ `DIEM: ${fmtUsd(p.diem)} (${fmtPct(p.diemChange24h)}) | 24h Vol: ${fmtUsd(p.diemVolume24h)}`,
28
+ "",
29
+ ];
30
+ for (const e of d.events) {
31
+ const label = TYPE_LABELS[e.type] || e.type.toUpperCase();
32
+ const name = e.ensName || e.username || `${e.address.slice(0, 8)}...`;
33
+ const bot = e.botLabel ? ` [${e.botLabel}]` : "";
34
+ const token = e.source === "swap"
35
+ ? (e.type.includes("diem") ? "DIEM" : "VVV")
36
+ : (e.source === "diem" ? "DIEM" : "VVV");
37
+ lines.push(`- ${label} ${fmtToken(e.amount, token)} by ${name}${bot} — ${fmtAgo(e.timestamp)}`);
38
+ }
39
+ return brandedResponse(lines.join("\n"), {
40
+ deepLink: "/terminal",
41
+ tip: "Use venicestats_large_trades for filtered large trades, or venicestats_wallet to look up any address.",
42
+ });
43
+ }
44
+ catch (err) {
45
+ return errorResponse(err instanceof Error ? err.message : String(err));
46
+ }
47
+ });
48
+ }
49
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/tools/live.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 registerMarketVolumeTool(server: McpServer): void;
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtUsd, fmtPct } from "../lib/format.js";
5
+ export function registerMarketVolumeTool(server) {
6
+ server.tool("venicestats_market_volume", "Get DEX trading volume for VVV or DIEM: total volume, buy/sell ratio, trader count, and breakdown by pool (Aerodrome, Uniswap, RFQ). Use when someone asks about trading activity, volume, or market dynamics.", {
7
+ token: z.enum(["VVV", "DIEM"]).default("VVV").describe("Token to view market data for"),
8
+ period: z.enum(["24h", "7d", "30d", "90d", "1y", "all"]).default("24h").describe("Lookback period"),
9
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ token, period }) => {
10
+ try {
11
+ const d = await apiGet("/api/markets", { token, period });
12
+ const volChange = d.kpis.volumePrev > 0
13
+ ? ((d.kpis.volume - d.kpis.volumePrev) / d.kpis.volumePrev) * 100
14
+ : 0;
15
+ const traderChange = d.kpis.tradersPrev > 0
16
+ ? ((d.kpis.traders - d.kpis.tradersPrev) / d.kpis.tradersPrev) * 100
17
+ : 0;
18
+ const lines = [
19
+ `## ${token} Market — ${period}`,
20
+ `Volume: ${fmtUsd(d.kpis.volume)} (${fmtPct(volChange)} vs prev period)`,
21
+ `Buy/Sell: ${d.kpis.buyPct}% buy / ${100 - d.kpis.buyPct}% sell`,
22
+ `Traders: ${d.kpis.traders.toLocaleString()} (${fmtPct(traderChange)}) | Swaps: ${d.kpis.swaps.toLocaleString()}`,
23
+ "",
24
+ `## Pool Breakdown`,
25
+ ...d.pools
26
+ .filter((p) => p.volume > 0)
27
+ .map((p) => `- **${p.name}** (${p.dex}): ${fmtUsd(p.volume)} (${p.volumePct}%) — ${p.swaps} swaps, ${p.buyPct}% buy`),
28
+ ];
29
+ return brandedResponse(lines.join("\n"), {
30
+ deepLink: `/markets?token=${token}&period=${period}`,
31
+ tip: "Use venicestats_large_trades for individual large trades, or venicestats_insider_flow for vesting recipient activity.",
32
+ });
33
+ }
34
+ catch (err) {
35
+ return errorResponse(err instanceof Error ? err.message : String(err));
36
+ }
37
+ });
38
+ }
39
+ //# sourceMappingURL=market-volume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"market-volume.js","sourceRoot":"","sources":["../../src/tools/market-volume.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 registerPriceTool(server: McpServer): void;
@@ -0,0 +1,28 @@
1
+ import { apiGet } from "../lib/api-client.js";
2
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
3
+ import { fmtUsd, fmtPct } from "../lib/format.js";
4
+ export function registerPriceTool(server) {
5
+ server.tool("venicestats_price", "Get current VVV and DIEM token prices with 24h changes, market cap, and FDV. Use this when someone asks about Venice token prices.", { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => {
6
+ try {
7
+ const data = await apiGet("/api/metrics");
8
+ const lines = [
9
+ `## VVV Price: ${fmtUsd(data.vvvPrice)} (${fmtPct(data.priceChange24h)})`,
10
+ `Market Cap: ${fmtUsd(data.marketCap)} | FDV: ${fmtUsd(data.fdv)}`,
11
+ "",
12
+ `## DIEM Price: ${fmtUsd(data.diemPrice)} (${fmtPct(data.diemPriceChange24h)})`,
13
+ `Market Cap: ${fmtUsd(data.diemMarketCap)} | FDV: ${fmtUsd(data.diemFdv)}`,
14
+ ];
15
+ if (data.priceStale) {
16
+ lines.push("", "⚠️ Price data may be stale — last updated: " + (data.priceLastUpdated ?? "unknown"));
17
+ }
18
+ return brandedResponse(lines.join("\n"), {
19
+ deepLink: "/",
20
+ tip: "Use venicestats_staking for yield and staking details, or venicestats_protocol_overview for a full snapshot.",
21
+ });
22
+ }
23
+ catch (err) {
24
+ return errorResponse(err instanceof Error ? err.message : String(err));
25
+ }
26
+ });
27
+ }
28
+ //# sourceMappingURL=price.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.js","sourceRoot":"","sources":["../../src/tools/price.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAelD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,oIAAoI,EACpI,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EACzF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAkB,cAAc,CAAC,CAAC;YAE3D,MAAM,KAAK,GAAG;gBACZ,iBAAiB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG;gBACzE,eAAe,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBAClE,EAAE;gBACF,kBAAkB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG;gBAC/E,eAAe,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;aAC3E,CAAC;YAEF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,6CAA6C,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,SAAS,CAAC,CAAC,CAAC;YACvG,CAAC;YAED,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvC,QAAQ,EAAE,GAAG;gBACb,GAAG,EAAE,8GAA8G;aACpH,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 registerProtocolOverviewTool(server: McpServer): void;
@@ -0,0 +1,86 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../lib/api-client.js";
3
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
4
+ import { fmtUsd, fmtToken, fmtPct, fmtRatio } from "../lib/format.js";
5
+ const CATEGORIES = ["token", "staking", "diem", "burns", "economics", "growth", "vesting"];
6
+ function formatCategory(cat, d) {
7
+ switch (cat) {
8
+ case "token":
9
+ return [
10
+ `## Token`,
11
+ `Price: ${fmtUsd(d.vvvPrice)} (${fmtPct(d.priceChange24h)})`,
12
+ `Market Cap: ${fmtUsd(d.marketCap)} | FDV: ${fmtUsd(d.fdv)}`,
13
+ `Total Supply: ${fmtToken(d.totalSupply, "VVV")}`,
14
+ `Circulating: ${fmtToken(d.circulatingSupply)} | Burned: ${fmtToken(d.burnedSupply)}`,
15
+ ];
16
+ case "staking":
17
+ return [
18
+ `## Staking`,
19
+ `Total Staked: ${fmtToken(d.totalStaked, "sVVV")} (${fmtRatio(d.stakingRatio)})`,
20
+ `APR: ${d.stakerApr.toFixed(1)}% | Locked: ${fmtToken(d.svvvLocked)} (${fmtRatio(d.lockRatio)})`,
21
+ `Emission: ${fmtToken(d.emissionPerYear, "VVV")}/year`,
22
+ ];
23
+ case "diem":
24
+ return [
25
+ `## DIEM`,
26
+ `Price: ${fmtUsd(d.diemPrice)} (${fmtPct(d.diemPriceChange24h)})`,
27
+ `Supply: ${fmtToken(d.diemSupply, "DIEM")} | Staked: ${fmtToken(d.diemStaked)} (${fmtRatio(d.diemStakeRatio)})`,
28
+ `Mint Rate: ${Math.round(d.mintRate)} sVVV/DIEM | Mint Cost: ${fmtUsd(d.mintCostUsd)}`,
29
+ `Market Discount: ${fmtRatio(1 - d.mintParity)} vs mint cost`,
30
+ `Break-even: ${d.diemBreakEvenDays} days | Remaining mintable: ${fmtToken(d.remainingMintable, "DIEM")}`,
31
+ ];
32
+ case "burns":
33
+ return [
34
+ `## Burns & Revenue`,
35
+ `Total Burned: ${fmtToken(d.totalBurnedFromEvents, "VVV")} (${fmtToken(d.organicBurned)} organic)`,
36
+ `Annualized Revenue: ${fmtUsd(d.burnRevenueAnnualized)}`,
37
+ `Deflation Rate: ${d.burnDeflationRate.toFixed(2)}%/year`,
38
+ ];
39
+ case "economics":
40
+ return [
41
+ `## Economics`,
42
+ `Ecosystem TVL: ${fmtUsd(d.ecosystemTvl)}`,
43
+ `Venice Revenue (est.): ${fmtUsd(d.veniceRevenue)}/year`,
44
+ `P/E Ratio: ${d.peRatio.toFixed(1)}`,
45
+ `Implied Confidence: ${d.impliedConfidence.toFixed(2)}x`,
46
+ ];
47
+ case "growth":
48
+ return [
49
+ `## Growth & Activity`,
50
+ `Net Flow (7d): ${fmtToken(d.netFlow7d, "VVV")}`,
51
+ `Staking Growth: 7d ${fmtPct(d.stakingGrowth7d)} | 30d ${fmtPct(d.stakingGrowth30d)}`,
52
+ `New Stakers (7d): ${d.newStakers7dCount} | Active Wallets: ${d.activeWallets7dCount}`,
53
+ `Cooldown: ${fmtToken(d.cooldownVvv, "VVV")} across ${d.cooldownWallets} wallets`,
54
+ ];
55
+ case "vesting":
56
+ return [
57
+ `## Vesting`,
58
+ `Locked: ${fmtToken(d.vestingTotalLocked, "VVV")}`,
59
+ `Daily Drip: ${fmtToken(d.vestingDailyDrip, "VVV")}/day`,
60
+ `Active Streams: ${d.vestingActiveStreams}`,
61
+ ];
62
+ default:
63
+ return [];
64
+ }
65
+ }
66
+ export function registerProtocolOverviewTool(server) {
67
+ server.tool("venicestats_protocol_overview", "Get a comprehensive Venice protocol snapshot with 40+ KPIs organized by category: token, staking, diem, burns, economics, growth, vesting. Use the category parameter to focus on one area, or omit it for the full picture. This is the most complete overview tool.", {
68
+ category: z.enum(CATEGORIES).optional().describe("Focus on a specific category. Omit for full overview."),
69
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ category }) => {
70
+ try {
71
+ const d = await apiGet("/api/metrics");
72
+ const cats = category ? [category] : [...CATEGORIES];
73
+ const sections = cats.flatMap((c) => [...formatCategory(c, d), ""]);
74
+ return brandedResponse(sections.join("\n"), {
75
+ deepLink: "/",
76
+ tip: category
77
+ ? `Omit the category parameter to see the full protocol overview.`
78
+ : "Use venicestats_price for a quick price check, or venicestats_wallet to look up a specific holder.",
79
+ });
80
+ }
81
+ catch (err) {
82
+ return errorResponse(err instanceof Error ? err.message : String(err));
83
+ }
84
+ });
85
+ }
86
+ //# sourceMappingURL=protocol-overview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol-overview.js","sourceRoot":"","sources":["../../src/tools/protocol-overview.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 registerSocialTool(server: McpServer): void;
@@ -0,0 +1,38 @@
1
+ import { apiGet, ApiError } from "../lib/api-client.js";
2
+ import { brandedResponse, errorResponse } from "../lib/branding.js";
3
+ export function registerSocialTool(server) {
4
+ server.tool("venicestats_social", "Get social and sentiment metrics for Venice: Twitter followers (@AskVenice, @ErikVoorhees), CoinGecko watchlist users, sentiment percentage, social volume, and social dominance. Use when someone asks about community sentiment, social metrics, or whether the mood is bullish or bearish.", { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => {
5
+ try {
6
+ const d = await apiGet("/api/social");
7
+ const lines = [
8
+ `## Venice Social Metrics`,
9
+ ];
10
+ if (d.twitterFollowers != null)
11
+ lines.push(`Twitter Followers: ${d.twitterFollowers.toLocaleString()}`);
12
+ if (d.watchlistUsers != null)
13
+ lines.push(`CoinGecko Watchlist: ${d.watchlistUsers.toLocaleString()}`);
14
+ if (d.sentimentUpPct != null)
15
+ lines.push(`Sentiment: ${d.sentimentUpPct}% bullish`);
16
+ if (d.marketCapRank != null)
17
+ lines.push(`Market Cap Rank: #${d.marketCapRank}`);
18
+ if (d.socialVolume != null)
19
+ lines.push(`Social Volume: ${Math.round(d.socialVolume)}`);
20
+ if (d.socialDominance != null)
21
+ lines.push(`Social Dominance: ${d.socialDominance.toFixed(4)}%`);
22
+ return brandedResponse(lines.join("\n"), {
23
+ deepLink: "/",
24
+ tip: "Use venicestats_buzz for recent articles and tweets about Venice.",
25
+ });
26
+ }
27
+ catch (err) {
28
+ if (err instanceof ApiError && (err.status === 404 || err.status === 500)) {
29
+ return brandedResponse("## Venice Social Metrics\n\nSocial data endpoint is not yet available — coming soon.\n\nVeniceStats tracks Twitter followers, CoinGecko watchlist/sentiment, and Santiment social volume. This data will be exposed via the API shortly.", {
30
+ deepLink: "/",
31
+ tip: "Use venicestats_buzz for recent articles and tweets about Venice in the meantime.",
32
+ });
33
+ }
34
+ return errorResponse(err instanceof Error ? err.message : String(err));
35
+ }
36
+ });
37
+ }
38
+ //# sourceMappingURL=social.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/tools/social.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAapE,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,+RAA+R,EAC/R,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EACzF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAiB,aAAa,CAAC,CAAC;YAEtD,MAAM,KAAK,GAAG;gBACZ,0BAA0B;aAC3B,CAAC;YAEF,IAAI,CAAC,CAAC,gBAAgB,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,gBAAgB,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YACxG,IAAI,CAAC,CAAC,cAAc,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YACtG,IAAI,CAAC,CAAC,cAAc,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,cAAc,WAAW,CAAC,CAAC;YACpF,IAAI,CAAC,CAAC,aAAa,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;YAChF,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACvF,IAAI,CAAC,CAAC,eAAe,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAEhG,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvC,QAAQ,EAAE,GAAG;gBACb,GAAG,EAAE,mEAAmE;aACzE,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,QAAQ,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC1E,OAAO,eAAe,CACpB,0OAA0O,EAC1O;oBACE,QAAQ,EAAE,GAAG;oBACb,GAAG,EAAE,mFAAmF;iBACzF,CACF,CAAC;YACJ,CAAC;YACD,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 registerStakingTool(server: McpServer): void;