@pvpwire/mcp-server
Advanced tools
+36
-2
@@ -409,5 +409,5 @@ #!/usr/bin/env node | ||
| } | ||
| registerTool('get_economy_arbitrage', "Cross-market arbitrage verdict for a tracked game economy (osrs, ffxiv): the widest sustained buy/sell spread to exploit, computed over PVPWire's own daily corpus. Free preview returns the single top pick (rate limited per client). Set full=true for the ranked table, volume-based risk flags, data freshness, and an AFTA Ed25519-signed receipt. Costs 10 credits ($0.10) and requires a PVPWIRE_TOKEN bearer token (buy at https://pvpwire.com/developers/agent-payments).", { | ||
| registerTool('get_economy_arbitrage', "Cross-market arbitrage verdict for a tracked game economy: the widest sustained buy/sell spread to exploit, computed over PVPWire's own daily corpus. Free preview returns the single top pick (rate limited per client) and covers osrs and ffxiv. Set full=true for the ranked table, volume-based risk flags, data freshness, and an AFTA Ed25519-signed receipt; the paid verdict covers osrs only. Costs 10 credits ($0.10) and requires a PVPWIRE_TOKEN bearer token (buy at https://pvpwire.com/developers/agent-payments).", { | ||
| game: z.enum(['osrs', 'ffxiv']).describe('Tracked economy.'), | ||
| full: z.boolean().optional().describe('true = paid full verdict (10 credits, needs PVPWIRE_TOKEN). Omit or false for the free top-pick preview.'), | ||
| full: z.boolean().optional().describe('true = paid full verdict, osrs only (10 credits, needs PVPWIRE_TOKEN). Omit or false for the free top-pick preview, which also covers ffxiv.'), | ||
| }, async ({ game, full }) => { | ||
@@ -420,2 +420,36 @@ const path = full | ||
| }); | ||
| registerTool('get_d2_breakpoint_verdict', "Diablo 2 breakpoint verdict: which frame tier a class hits at its current fcr/fhr/fbr/ias percent, the next breakpoint and its gap, and (paid) the ranked runewords, uniques and set items that close it. Computed over PVPWire's independently compiled tables. Free preview returns the headline ruling; set full=true for the ranked gear table and an AFTA Ed25519-signed receipt (10 credits, $0.10, needs PVPWIRE_TOKEN).", { | ||
| class: z | ||
| .enum(['amazon', 'assassin', 'barbarian', 'druid', 'necromancer', 'paladin', 'sorceress']) | ||
| .describe('Diablo 2 class.'), | ||
| stat: z.enum(['fcr', 'fhr', 'fbr', 'ias']).describe('Frame stat: faster cast rate, faster hit recovery, faster block rate, or increased attack speed. Availability varies by class.'), | ||
| current: z.number().int().min(0).max(1000).optional().describe('Current percent of the stat. Default 0.'), | ||
| full: z.boolean().optional().describe('true = paid full verdict with the ranked gear table (10 credits, needs PVPWIRE_TOKEN). Omit or false for the free preview.'), | ||
| }, async ({ class: cls, stat, current, full }) => { | ||
| const qs = `class=${cls}&stat=${stat}¤t=${current ?? 0}`; | ||
| const path = full ? `/premium/d2/breakpoint-verdict?${qs}` : `/preview/d2/breakpoint-verdict?${qs}`; | ||
| const data = (await fetchJSON(path, full ? { auth: true } : {})); | ||
| const lines = []; | ||
| if (typeof data.verdict === 'string') | ||
| lines.push(sanitizeForLLM(data.verdict)); | ||
| for (const c of data.contexts ?? []) { | ||
| if (c.context) { | ||
| lines.push(`Context (${sanitizeForLLM(c.context)}): ${c.current_frames} frames now${c.next ? `, next ${c.next.percent}% for ${c.next.frames} frames (gap ${c.next.gap}%)` : ', final tier'}.`); | ||
| } | ||
| } | ||
| const gear = data.gear; | ||
| if (gear?.contributors?.length) { | ||
| lines.push('Top contributors:'); | ||
| for (const g of gear.contributors.slice(0, 10)) { | ||
| lines.push(`- ${sanitizeForLLM(g.name)} (${g.type}, ${sanitizeForLLM(g.slot)}): +${g.value}%`); | ||
| } | ||
| } | ||
| if (gear?.single_item_closers?.length) { | ||
| lines.push(`Single-item closers: ${gear.single_item_closers.map((g) => `${sanitizeForLLM(g.name)} (+${g.value}%)`).join(', ')}.`); | ||
| } | ||
| if (data.billing && typeof data.billing.credits_remaining === 'number') { | ||
| lines.push(`Credits remaining: ${data.billing.credits_remaining}.`); | ||
| } | ||
| return text(lines.join('\n')); | ||
| }); | ||
| // ---- connect ---- | ||
@@ -422,0 +456,0 @@ async function main() { |
+1
-1
| { | ||
| "name": "@pvpwire/mcp-server", | ||
| "version": "1.0.3", | ||
| "version": "1.0.5", | ||
| "description": "Competitive-gaming data for AI agents: hand-compiled game-mechanics datasets for Diablo 2, Path of Exile, Diablo 3 and Guild Wars 2, plus live player counts, Twitch viewers, news, and game-economy snapshots.", | ||
@@ -5,0 +5,0 @@ "mcpName": "com.pvpwire/pvpwire", |
39811
6.81%691
5.34%