snowbll-mcp 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.
package/dist/index.js ADDED
@@ -0,0 +1,391 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Snowbll MCP Server
4
+ *
5
+ * Exposes Snowbll Gaming Behaviour Intelligence to AI agents (Claude, Cursor,
6
+ * Windsurf, OpenAI Agents SDK, LangChain, CrewAI, AutoGen, Vercel AI SDK, and
7
+ * custom TypeScript/Python agents) over the Model Context Protocol via stdio.
8
+ *
9
+ * This server is a TOOL PROVIDER, not the agent. The calling agent decides when
10
+ * to invoke a tool; Snowbll returns structured behaviour intelligence.
11
+ */
12
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14
+ import { z } from "zod";
15
+ import { SnowbllClient } from "./client.js";
16
+ import { CommunityClient } from "./communityClient.js";
17
+ import { CrossCheckClient } from "./crossCheckClient.js";
18
+ import * as schemas from "./schemas.js";
19
+ import { registerResources } from "./resources.js";
20
+ import { registerPrompts } from "./prompts.js";
21
+ const client = new SnowbllClient();
22
+ const community = new CommunityClient();
23
+ const reco = new CrossCheckClient();
24
+ const server = new McpServer({
25
+ name: "snowbll-mcp",
26
+ version: "0.1.0",
27
+ });
28
+ /** Wrap any JSON-serializable value as an MCP text-content result. */
29
+ function jsonResult(data) {
30
+ return {
31
+ content: [
32
+ { type: "text", text: JSON.stringify(data, null, 2) },
33
+ ],
34
+ };
35
+ }
36
+ /**
37
+ * Wrap a value with both text content and structured output. The MCP SDK types
38
+ * structuredContent loosely and validates it against the tool's outputSchema at
39
+ * runtime, so the cast here is safe (the data already matches the schema).
40
+ */
41
+ function out(data) {
42
+ return {
43
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
44
+ structuredContent: data,
45
+ };
46
+ }
47
+ const readOnly = { readOnlyHint: true };
48
+ // ---------------------------------------------------------------------------
49
+ // 1. get_player_overview
50
+ // ---------------------------------------------------------------------------
51
+ server.registerTool("get_player_overview", {
52
+ title: "Get player overview",
53
+ description: "Get the player's Snowbll overview: total games, wishlist, posts, dev follows, persona match, current objective, and high-level gaming identity. Call this first to ground any reasoning about who the player is.",
54
+ outputSchema: schemas.PlayerOverviewSchema.shape,
55
+ annotations: readOnly,
56
+ }, async () => out(await client.getPlayerOverview()));
57
+ // ---------------------------------------------------------------------------
58
+ // 2. get_playstyle_dna
59
+ // ---------------------------------------------------------------------------
60
+ server.registerTool("get_playstyle_dna", {
61
+ title: "Get playstyle DNA",
62
+ description: "Get the player's playstyle DNA traits (systems thinking, progression seeking, exploration, creativity, competition, story-driven) with scores and tiers. Use to understand the player's underlying preferences.",
63
+ outputSchema: schemas.PlaystyleDnaSchema.shape,
64
+ annotations: readOnly,
65
+ }, async () => out(await client.getPlaystyleDna()));
66
+ // ---------------------------------------------------------------------------
67
+ // 3. get_persona_cards
68
+ // ---------------------------------------------------------------------------
69
+ server.registerTool("get_persona_cards", {
70
+ title: "Get persona cards",
71
+ description: "Get the player's Snowbll persona cards with rarity, level, progress, and behavioral evidence. Use to describe the player's gaming identity in concrete, evidence-backed terms.",
72
+ outputSchema: schemas.PersonaCardsSchema.shape,
73
+ annotations: readOnly,
74
+ }, async () => out(await client.getPersonaCards()));
75
+ // ---------------------------------------------------------------------------
76
+ // 4. get_activity_patterns
77
+ // ---------------------------------------------------------------------------
78
+ server.registerTool("get_activity_patterns", {
79
+ title: "Get activity patterns",
80
+ description: "Get the player's activity patterns: most active hours, session length distribution, platform distribution, and play rhythm. Use to reason about when and how long the player plays.",
81
+ outputSchema: schemas.ActivityPatternsSchema.shape,
82
+ annotations: readOnly,
83
+ }, async () => out(await client.getActivityPatterns()));
84
+ // ---------------------------------------------------------------------------
85
+ // 5. get_completion_behavior
86
+ // ---------------------------------------------------------------------------
87
+ server.registerTool("get_completion_behavior", {
88
+ title: "Get completion behavior",
89
+ description: "Analyze what the player finishes versus abandons, which categories complete well, and the signals that cause drop-off. Use when predicting whether the player will finish a game.",
90
+ outputSchema: schemas.CompletionBehaviorSchema.shape,
91
+ annotations: readOnly,
92
+ }, async () => out(await client.getCompletionBehavior()));
93
+ // ---------------------------------------------------------------------------
94
+ // 6. get_purchase_behavior
95
+ // ---------------------------------------------------------------------------
96
+ server.registerTool("get_purchase_behavior", {
97
+ title: "Get purchase behavior",
98
+ description: "Get the player's purchase behavior and the gap between what they buy and what they actually play. Returns aggregate intelligence by default.",
99
+ inputSchema: {
100
+ includeSensitiveSignals: z
101
+ .boolean()
102
+ .default(false)
103
+ .describe("When true, include raw / overly specific purchase-level detail. Default false returns aggregates only."),
104
+ },
105
+ outputSchema: schemas.PurchaseBehaviorSchema.shape,
106
+ annotations: readOnly,
107
+ }, async ({ includeSensitiveSignals }) => out(await client.getPurchaseBehavior(includeSensitiveSignals)));
108
+ // ---------------------------------------------------------------------------
109
+ // 7. detect_genre_mismatch
110
+ // ---------------------------------------------------------------------------
111
+ server.registerTool("detect_genre_mismatch", {
112
+ title: "Detect genre mismatch",
113
+ description: "Detect mismatch between what the player buys, claims to like, actually plays, and completes. Use to surface where stated taste diverges from observed behaviour.",
114
+ inputSchema: {
115
+ includePurchaseSignals: z
116
+ .boolean()
117
+ .default(false)
118
+ .describe("Include purchase-derived evidence for each mismatch."),
119
+ includeCompletionSignals: z
120
+ .boolean()
121
+ .default(true)
122
+ .describe("Include completion-derived evidence for each mismatch."),
123
+ },
124
+ outputSchema: schemas.GenreMismatchResultSchema.shape,
125
+ annotations: readOnly,
126
+ }, async ({ includePurchaseSignals, includeCompletionSignals }) => out(await client.detectGenreMismatch(includePurchaseSignals, includeCompletionSignals)));
127
+ // ---------------------------------------------------------------------------
128
+ // 8. analyze_player_behaviour
129
+ // ---------------------------------------------------------------------------
130
+ server.registerTool("analyze_player_behaviour", {
131
+ title: "Analyze player behaviour",
132
+ description: "Analyze the player's gaming behaviour using persona, playstyle DNA, session activity, completion behavior, purchase signals, and taste patterns. The primary 'understand this player' tool.",
133
+ inputSchema: {
134
+ depth: z
135
+ .enum(["light", "standard", "deep"])
136
+ .default("standard")
137
+ .describe("Analysis depth. 'light' = summary + key traits, 'standard' = full analysis, 'deep' = adds correlations, predicted preferences, and risk factors."),
138
+ includeEvidence: z
139
+ .boolean()
140
+ .default(true)
141
+ .describe("Include the behavioral evidence list backing the analysis."),
142
+ },
143
+ outputSchema: schemas.PlayerBehaviourAnalysisSchema.shape,
144
+ annotations: readOnly,
145
+ }, async ({ depth, includeEvidence }) => out(await client.analyzePlayerBehaviour(depth, includeEvidence)));
146
+ // ---------------------------------------------------------------------------
147
+ // 9. explain_taste_pattern
148
+ // ---------------------------------------------------------------------------
149
+ server.registerTool("explain_taste_pattern", {
150
+ title: "Explain taste pattern",
151
+ description: "Explain why the player likes, dislikes, finishes, or abandons certain types of games, given a natural-language topic. Returns an explanation, supporting signals, and actionable advice.",
152
+ inputSchema: {
153
+ topic: z
154
+ .string()
155
+ .min(1)
156
+ .describe("A natural-language question about the player's taste, e.g. 'Why do I abandon open-world RPGs?'"),
157
+ },
158
+ outputSchema: schemas.TastePatternSchema.shape,
159
+ annotations: readOnly,
160
+ }, async ({ topic }) => out(await client.explainTastePattern(topic)));
161
+ // ---------------------------------------------------------------------------
162
+ // 10. predict_game_fit
163
+ // ---------------------------------------------------------------------------
164
+ server.registerTool("predict_game_fit", {
165
+ title: "Predict game fit",
166
+ description: "Predict whether a specific game fits the player's behaviour: fit score, finish likelihood, drop-off risk, and an explanation of why it fits or may not.",
167
+ inputSchema: {
168
+ gameTitle: z
169
+ .string()
170
+ .min(1)
171
+ .describe("The game title to evaluate, e.g. 'Factorio'."),
172
+ platform: z
173
+ .enum(["steam", "playstation", "xbox", "switch", "epic", "unknown"])
174
+ .default("unknown")
175
+ .describe("Platform the player would play on."),
176
+ },
177
+ outputSchema: schemas.GameFitSchema.shape,
178
+ annotations: readOnly,
179
+ }, async ({ gameTitle, platform }) => out(await client.predictGameFit(gameTitle, platform)));
180
+ // ---------------------------------------------------------------------------
181
+ // 11. compare_games_for_player
182
+ // ---------------------------------------------------------------------------
183
+ server.registerTool("compare_games_for_player", {
184
+ title: "Compare games for player",
185
+ description: "Compare 2–5 games against the player's Snowbll persona and rank them by behavioural fit, explaining which one fits best.",
186
+ inputSchema: {
187
+ games: z
188
+ .array(z.string().min(1))
189
+ .min(2)
190
+ .max(5)
191
+ .describe("2 to 5 game titles to compare for this player."),
192
+ },
193
+ outputSchema: schemas.CompareResultSchema.shape,
194
+ annotations: readOnly,
195
+ }, async ({ games }) => out(await client.compareGamesForPlayer(games)));
196
+ // ---------------------------------------------------------------------------
197
+ // 12. recommend_games
198
+ // ---------------------------------------------------------------------------
199
+ server.registerTool("recommend_games", {
200
+ title: "Recommend games",
201
+ description: "Recommend games based on the player's Snowbll persona, playstyle DNA, session style, completion behavior, and a chosen objective. Recommendations reflect behavioural fit, not genre alone.",
202
+ inputSchema: {
203
+ objective: z
204
+ .enum([
205
+ "likely_to_finish",
206
+ "hidden_gems",
207
+ "deep_systems",
208
+ "comfort_games",
209
+ "short_sessions",
210
+ "high_progression",
211
+ ])
212
+ .default("likely_to_finish")
213
+ .describe("What the recommendations should optimize for."),
214
+ limit: z
215
+ .number()
216
+ .int()
217
+ .min(1)
218
+ .max(20)
219
+ .default(5)
220
+ .describe("Maximum number of games to return."),
221
+ },
222
+ outputSchema: schemas.RecommendResultSchema.shape,
223
+ annotations: readOnly,
224
+ }, async ({ objective, limit }) => out(await client.recommendGames(objective, limit)));
225
+ // ===========================================================================
226
+ // Community Recommendation Engine tools (forum / discussions / dev updates)
227
+ // ===========================================================================
228
+ const COMMUNITY_OBJECTIVES = [
229
+ "learn_strategy",
230
+ "find_hidden_gems",
231
+ "join_discussion",
232
+ "avoid_spoilers",
233
+ "get_build_ideas",
234
+ "discover_devs",
235
+ "follow_meta",
236
+ "find_people_like_me",
237
+ "catch_up_on_community",
238
+ "solve_problem",
239
+ "low_energy_browse",
240
+ "deep_systems_discussion",
241
+ ];
242
+ // ---------------------------------------------------------------------------
243
+ // 13. recommend_forum_threads
244
+ // ---------------------------------------------------------------------------
245
+ server.registerTool("recommend_forum_threads", {
246
+ title: "Recommend forum threads",
247
+ description: "Recommend forum threads, discussions, guides, and developer updates for the player based on behavioural fit and a community objective. Ranks on topic match, systems/optimization relevance, discussion quality, and spoiler/toxicity risk — not category alone.",
248
+ inputSchema: {
249
+ objective: z
250
+ .enum(COMMUNITY_OBJECTIVES)
251
+ .default("learn_strategy")
252
+ .describe("What the thread recommendations should optimize for."),
253
+ limit: z
254
+ .number()
255
+ .int()
256
+ .min(1)
257
+ .max(20)
258
+ .default(5)
259
+ .describe("Maximum number of threads to return."),
260
+ avoidSpoilers: z
261
+ .boolean()
262
+ .default(false)
263
+ .describe("When true, exclude major-spoiler threads."),
264
+ maxToxicity: z
265
+ .enum(["low", "medium", "high"])
266
+ .optional()
267
+ .describe("Drop threads whose computed toxicity exceeds this ceiling."),
268
+ gameTitle: z
269
+ .string()
270
+ .min(1)
271
+ .optional()
272
+ .describe("Restrict to a single game's community, e.g. 'Factorio'."),
273
+ },
274
+ }, async ({ objective, limit, avoidSpoilers, maxToxicity, gameTitle }) => jsonResult(await community.recommendForumThreads({
275
+ objective,
276
+ limit,
277
+ avoidSpoilers,
278
+ maxToxicity,
279
+ gameTitle,
280
+ })));
281
+ // ---------------------------------------------------------------------------
282
+ // 14. predict_thread_fit
283
+ // ---------------------------------------------------------------------------
284
+ server.registerTool("predict_thread_fit", {
285
+ title: "Predict thread fit",
286
+ description: "Predict whether a specific forum thread fits the player: fit score, topic match, engagement likelihood, spoiler/toxicity risk, and why it fits or may not.",
287
+ inputSchema: {
288
+ threadTitle: z
289
+ .string()
290
+ .min(1)
291
+ .describe("The thread title to evaluate, e.g. 'How to optimize early-game factory layouts without overbuilding'."),
292
+ },
293
+ }, async ({ threadTitle }) => jsonResult(await community.predictThreadFit(threadTitle)));
294
+ // ---------------------------------------------------------------------------
295
+ // 15. compare_threads_for_player
296
+ // ---------------------------------------------------------------------------
297
+ server.registerTool("compare_threads_for_player", {
298
+ title: "Compare threads for player",
299
+ description: "Compare 2–5 forum threads against the player's behaviour and rank them by fit, surfacing the best pick and each thread's spoiler/toxicity risk.",
300
+ inputSchema: {
301
+ threads: z
302
+ .array(z.string().min(1))
303
+ .min(2)
304
+ .max(5)
305
+ .describe("2 to 5 thread titles to compare for this player."),
306
+ },
307
+ }, async ({ threads }) => jsonResult(await community.compareThreadsForPlayer(threads)));
308
+ // ---------------------------------------------------------------------------
309
+ // 16. explain_thread_recommendation
310
+ // ---------------------------------------------------------------------------
311
+ server.registerTool("explain_thread_recommendation", {
312
+ title: "Explain thread recommendation",
313
+ description: "Explain, in deterministic natural language, why a forum thread does or does not fit the player — main reasons, risks, and advice. Grounded in behavioural signals, not invented.",
314
+ inputSchema: {
315
+ threadTitle: z
316
+ .string()
317
+ .min(1)
318
+ .describe("The thread title to explain."),
319
+ },
320
+ }, async ({ threadTitle }) => jsonResult(await community.explainThreadRecommendation(threadTitle)));
321
+ // ---------------------------------------------------------------------------
322
+ // 17. detect_threads_to_avoid
323
+ // ---------------------------------------------------------------------------
324
+ server.registerTool("detect_threads_to_avoid", {
325
+ title: "Detect threads to avoid",
326
+ description: "Surface forum threads the player should avoid — spoiler-heavy story discussion, competitive flame wars, low-quality drama — ranked by how strongly they conflict with the player's avoidance signals.",
327
+ inputSchema: {
328
+ limit: z
329
+ .number()
330
+ .int()
331
+ .min(1)
332
+ .max(20)
333
+ .default(5)
334
+ .describe("Maximum number of threads to flag."),
335
+ },
336
+ }, async ({ limit }) => jsonResult(await community.detectThreadsToAvoid(limit)));
337
+ // ===========================================================================
338
+ // Cross-check (consensus) tool — two engines validate each other
339
+ // ===========================================================================
340
+ const CROSSCHECK_OBJECTIVES = [
341
+ "likely_to_finish",
342
+ "hidden_gems",
343
+ "deep_systems",
344
+ "comfort_games",
345
+ "short_sessions",
346
+ "high_progression",
347
+ ];
348
+ // ---------------------------------------------------------------------------
349
+ // 18. crosscheck_recommendations
350
+ // ---------------------------------------------------------------------------
351
+ server.registerTool("crosscheck_recommendations", {
352
+ title: "Cross-check recommendations",
353
+ description: "Recommend games VALIDATED by two independent Snowbll engines — the Recommendation Engine and the Persona Engine's own recommender. The engines deliberate: picks both agree on are high-confidence 'consensus'; disputed picks are adjudicated by a neutral referee (a deep game-fit prediction) and either kept as 'referee-validated' or rejected as 'contested'. Returns a validated, confidence-ranked list plus an overall agreement score and the round-by-round deliberation log. Use this when you want the most trustworthy recommendation — agreement equals confidence — instead of a single engine's opinion.",
354
+ inputSchema: {
355
+ objective: z
356
+ .enum(CROSSCHECK_OBJECTIVES)
357
+ .default("deep_systems")
358
+ .describe("What the cross-checked recommendations should optimize for."),
359
+ limit: z
360
+ .number()
361
+ .int()
362
+ .min(1)
363
+ .max(20)
364
+ .default(5)
365
+ .describe("Maximum number of validated games to return."),
366
+ includeCommunity: z
367
+ .boolean()
368
+ .default(true)
369
+ .describe("Include the Community Engine as a third cross-check lens (a community-interest signal). Default true = 3-way cross-check; set false for the leaner Recommendation-vs-Persona pass."),
370
+ },
371
+ annotations: readOnly,
372
+ }, async ({ objective, limit, includeCommunity }) => jsonResult(await reco.crossCheckRecommendations({ objective, limit, includeCommunity })));
373
+ // ===========================================================================
374
+ // Resources & Prompts
375
+ // ===========================================================================
376
+ registerResources(server, client);
377
+ registerPrompts(server);
378
+ // ---------------------------------------------------------------------------
379
+ // Boot
380
+ // ---------------------------------------------------------------------------
381
+ async function main() {
382
+ const transport = new StdioServerTransport();
383
+ await server.connect(transport);
384
+ // stdout is reserved for the MCP protocol; log to stderr only.
385
+ console.error(`[snowbll-mcp] running on stdio — game data mode: ${client.mode}, community data mode: ${community.mode}, cross-check data mode: ${reco.mode}`);
386
+ }
387
+ main().catch((error) => {
388
+ console.error("[snowbll-mcp] fatal error during startup:", error);
389
+ process.exit(1);
390
+ });
391
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}