hearthstone-oracle 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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/data/db.d.ts +49 -0
  4. package/dist/data/db.d.ts.map +1 -0
  5. package/dist/data/db.js +109 -0
  6. package/dist/data/db.js.map +1 -0
  7. package/dist/data/hearthstone.d.ts +40 -0
  8. package/dist/data/hearthstone.d.ts.map +1 -0
  9. package/dist/data/hearthstone.js +58 -0
  10. package/dist/data/hearthstone.js.map +1 -0
  11. package/dist/data/pipeline.d.ts +36 -0
  12. package/dist/data/pipeline.d.ts.map +1 -0
  13. package/dist/data/pipeline.js +90 -0
  14. package/dist/data/pipeline.js.map +1 -0
  15. package/dist/data/schema.sql +111 -0
  16. package/dist/data/strategy-seed.d.ts +3 -0
  17. package/dist/data/strategy-seed.d.ts.map +1 -0
  18. package/dist/data/strategy-seed.js +512 -0
  19. package/dist/data/strategy-seed.js.map +1 -0
  20. package/dist/format.d.ts +63 -0
  21. package/dist/format.d.ts.map +1 -0
  22. package/dist/format.js +331 -0
  23. package/dist/format.js.map +1 -0
  24. package/dist/knowledge/archetype-classifier.d.ts +19 -0
  25. package/dist/knowledge/archetype-classifier.d.ts.map +1 -0
  26. package/dist/knowledge/archetype-classifier.js +232 -0
  27. package/dist/knowledge/archetype-classifier.js.map +1 -0
  28. package/dist/server.d.ts +5 -0
  29. package/dist/server.d.ts.map +1 -0
  30. package/dist/server.js +269 -0
  31. package/dist/server.js.map +1 -0
  32. package/dist/tools/analyze-deck.d.ts +45 -0
  33. package/dist/tools/analyze-deck.d.ts.map +1 -0
  34. package/dist/tools/analyze-deck.js +159 -0
  35. package/dist/tools/analyze-deck.js.map +1 -0
  36. package/dist/tools/decode-deck.d.ts +30 -0
  37. package/dist/tools/decode-deck.d.ts.map +1 -0
  38. package/dist/tools/decode-deck.js +127 -0
  39. package/dist/tools/decode-deck.js.map +1 -0
  40. package/dist/tools/explain-concept.d.ts +26 -0
  41. package/dist/tools/explain-concept.d.ts.map +1 -0
  42. package/dist/tools/explain-concept.js +34 -0
  43. package/dist/tools/explain-concept.js.map +1 -0
  44. package/dist/tools/get-archetype.d.ts +29 -0
  45. package/dist/tools/get-archetype.d.ts.map +1 -0
  46. package/dist/tools/get-archetype.js +47 -0
  47. package/dist/tools/get-archetype.js.map +1 -0
  48. package/dist/tools/get-card.d.ts +13 -0
  49. package/dist/tools/get-card.d.ts.map +1 -0
  50. package/dist/tools/get-card.js +71 -0
  51. package/dist/tools/get-card.js.map +1 -0
  52. package/dist/tools/get-class-identity.d.ts +43 -0
  53. package/dist/tools/get-class-identity.d.ts.map +1 -0
  54. package/dist/tools/get-class-identity.js +69 -0
  55. package/dist/tools/get-class-identity.js.map +1 -0
  56. package/dist/tools/get-keyword.d.ts +30 -0
  57. package/dist/tools/get-keyword.d.ts.map +1 -0
  58. package/dist/tools/get-keyword.js +88 -0
  59. package/dist/tools/get-keyword.js.map +1 -0
  60. package/dist/tools/get-matchup.d.ts +32 -0
  61. package/dist/tools/get-matchup.d.ts.map +1 -0
  62. package/dist/tools/get-matchup.js +41 -0
  63. package/dist/tools/get-matchup.js.map +1 -0
  64. package/dist/tools/search-cards.d.ts +43 -0
  65. package/dist/tools/search-cards.d.ts.map +1 -0
  66. package/dist/tools/search-cards.js +167 -0
  67. package/dist/tools/search-cards.js.map +1 -0
  68. package/package.json +50 -0
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ // --- Input Schema ---
3
+ export const GetClassIdentityInput = z.object({
4
+ class_name: z
5
+ .string()
6
+ .optional()
7
+ .describe('Class name (e.g. "Mage", "Warrior"). Omit to get an overview of all classes.'),
8
+ });
9
+ // --- Helpers ---
10
+ function parseJson(raw) {
11
+ if (!raw)
12
+ return [];
13
+ try {
14
+ return JSON.parse(raw);
15
+ }
16
+ catch {
17
+ return [];
18
+ }
19
+ }
20
+ function toClassIdentityInfo(row) {
21
+ return {
22
+ class: row.class,
23
+ identity: row.identity,
24
+ hero_power_name: row.hero_power_name,
25
+ hero_power_cost: row.hero_power_cost,
26
+ hero_power_effect: row.hero_power_effect,
27
+ hero_power_implications: row.hero_power_implications,
28
+ historical_archetypes: parseJson(row.historical_archetypes),
29
+ strengths: parseJson(row.strengths),
30
+ weaknesses: parseJson(row.weaknesses),
31
+ early_game: row.early_game,
32
+ mid_game: row.mid_game,
33
+ late_game: row.late_game,
34
+ };
35
+ }
36
+ export function getClassIdentity(db, input) {
37
+ // If no class_name provided, return overview of all classes
38
+ if (!input.class_name) {
39
+ const rows = db
40
+ .prepare('SELECT class, identity, hero_power_name FROM class_identities ORDER BY class')
41
+ .all();
42
+ return {
43
+ found: true,
44
+ overview: true,
45
+ classes: rows,
46
+ };
47
+ }
48
+ // Single class lookup (case-insensitive)
49
+ const row = db
50
+ .prepare('SELECT * FROM class_identities WHERE LOWER(class) = LOWER(?)')
51
+ .get(input.class_name);
52
+ if (row) {
53
+ return {
54
+ found: true,
55
+ identity: toClassIdentityInfo(row),
56
+ };
57
+ }
58
+ // Not found — suggest similar entries via LIKE
59
+ const suggestions = db
60
+ .prepare('SELECT class FROM class_identities WHERE LOWER(class) LIKE LOWER(?) LIMIT 5')
61
+ .all(`%${input.class_name}%`);
62
+ const suggestionNames = suggestions.map((s) => s.class);
63
+ return {
64
+ found: false,
65
+ message: `No class found matching "${input.class_name}".`,
66
+ suggestions: suggestionNames.length > 0 ? suggestionNames : undefined,
67
+ };
68
+ }
69
+ //# sourceMappingURL=get-class-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-class-identity.js","sourceRoot":"","sources":["../../src/tools/get-class-identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,uBAAuB;AAEvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,8EAA8E,CAAC;CAC5F,CAAC,CAAC;AAgCH,kBAAkB;AAElB,SAAS,SAAS,CAAC,GAAkB;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAmBD,SAAS,mBAAmB,CAAC,GAAqB;IAChD,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;QACxC,uBAAuB,EAAE,GAAG,CAAC,uBAAuB;QACpD,qBAAqB,EAAE,SAAS,CAAC,GAAG,CAAC,qBAAqB,CAAC;QAC3D,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;QACnC,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;QACrC,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,EAAqB,EACrB,KAAgC;IAEhC,4DAA4D;IAC5D,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,EAAE;aACZ,OAAO,CAAC,8EAA8E,CAAC;aACvF,GAAG,EAA0B,CAAC;QAEjC,OAAO;YACL,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,yCAAyC;IACzC,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CAAC,8DAA8D,CAAC;SACvE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAiC,CAAC;IAEzD,IAAI,GAAG,EAAE,CAAC;QACR,OAAO;YACL,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,mBAAmB,CAAC,GAAG,CAAC;SACnC,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,MAAM,WAAW,GAAG,EAAE;SACnB,OAAO,CAAC,6EAA6E,CAAC;SACtF,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,GAAG,CAA6B,CAAC;IAE5D,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAExD,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,4BAA4B,KAAK,CAAC,UAAU,IAAI;QACzD,WAAW,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;KACtE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type Database from 'better-sqlite3';
2
+ import { z } from 'zod';
3
+ import type { CardSummary } from '../format.js';
4
+ export declare const GetKeywordInput: z.ZodObject<{
5
+ name: z.ZodString;
6
+ player_class: z.ZodOptional<z.ZodString>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ name: string;
9
+ player_class?: string | undefined;
10
+ }, {
11
+ name: string;
12
+ player_class?: string | undefined;
13
+ }>;
14
+ export type GetKeywordInputType = z.infer<typeof GetKeywordInput>;
15
+ export interface KeywordInfo {
16
+ name: string;
17
+ description: string;
18
+ related_keywords: string[];
19
+ }
20
+ export type GetKeywordResult = {
21
+ found: true;
22
+ keyword: KeywordInfo;
23
+ cards: CardSummary[];
24
+ } | {
25
+ found: false;
26
+ message: string;
27
+ suggestions?: string[];
28
+ };
29
+ export declare function getKeyword(db: Database.Database, input: GetKeywordInputType): GetKeywordResult;
30
+ //# sourceMappingURL=get-keyword.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-keyword.d.ts","sourceRoot":"","sources":["../../src/tools/get-keyword.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD,eAAO,MAAM,eAAe;;;;;;;;;EAM1B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIlE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,GAC3D;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA6B9D,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,mBAAmB,GACzB,gBAAgB,CA8DlB"}
@@ -0,0 +1,88 @@
1
+ import { z } from 'zod';
2
+ // --- Input Schema ---
3
+ export const GetKeywordInput = z.object({
4
+ name: z.string().describe('Keyword name (e.g. "Deathrattle", "Battlecry")'),
5
+ player_class: z
6
+ .string()
7
+ .optional()
8
+ .describe('Filter related cards by class (e.g. MAGE, WARRIOR)'),
9
+ });
10
+ // --- Helpers ---
11
+ function parseJson(raw) {
12
+ if (!raw)
13
+ return [];
14
+ try {
15
+ return JSON.parse(raw);
16
+ }
17
+ catch {
18
+ return [];
19
+ }
20
+ }
21
+ function toCardSummary(row) {
22
+ return {
23
+ name: row.name,
24
+ mana_cost: row.mana_cost,
25
+ type: row.type,
26
+ player_class: row.player_class,
27
+ rarity: row.rarity,
28
+ text: row.text ? row.text.split('\n')[0] : null,
29
+ attack: row.attack,
30
+ health: row.health,
31
+ keywords: parseJson(row.keywords),
32
+ };
33
+ }
34
+ // --- Handler ---
35
+ export function getKeyword(db, input) {
36
+ // 1. Look up keyword in keywords table (case-insensitive)
37
+ const keywordRow = db
38
+ .prepare('SELECT * FROM keywords WHERE LOWER(name) = LOWER(?)')
39
+ .get(input.name);
40
+ // 2. Find cards that have this keyword in their keywords JSON
41
+ // The keywords JSON stores mechanics like "BATTLECRY", "TAUNT", etc.
42
+ // We search case-insensitively by upper-casing the keyword and replacing spaces with underscores
43
+ const mechanicName = input.name.toUpperCase().replace(/\s+/g, '_');
44
+ let cardSql = `SELECT * FROM cards WHERE keywords LIKE ? AND collectible = 1`;
45
+ const cardParams = [`%${mechanicName}%`];
46
+ if (input.player_class) {
47
+ cardSql += ' AND UPPER(player_class) = UPPER(?)';
48
+ cardParams.push(input.player_class);
49
+ }
50
+ cardSql += ' ORDER BY name LIMIT 25';
51
+ const cardRows = db.prepare(cardSql).all(...cardParams);
52
+ const cards = cardRows.map(toCardSummary);
53
+ // 3. If keyword found in table, return it with cards
54
+ if (keywordRow) {
55
+ return {
56
+ found: true,
57
+ keyword: {
58
+ name: keywordRow.name,
59
+ description: keywordRow.description,
60
+ related_keywords: parseJson(keywordRow.related_keywords),
61
+ },
62
+ cards,
63
+ };
64
+ }
65
+ // 4. If keyword not in table but we found cards with it, still return found
66
+ if (cards.length > 0) {
67
+ return {
68
+ found: true,
69
+ keyword: {
70
+ name: input.name,
71
+ description: `Cards with the ${input.name} mechanic.`,
72
+ related_keywords: [],
73
+ },
74
+ cards,
75
+ };
76
+ }
77
+ // 5. Not found — provide suggestions via LIKE match on partial name
78
+ const suggestions = db
79
+ .prepare('SELECT name FROM keywords WHERE LOWER(name) LIKE LOWER(?) LIMIT 5')
80
+ .all(`%${input.name}%`);
81
+ const suggestionNames = suggestions.map((s) => s.name);
82
+ return {
83
+ found: false,
84
+ message: `No keyword found matching "${input.name}".`,
85
+ suggestions: suggestionNames.length > 0 ? suggestionNames : undefined,
86
+ };
87
+ }
88
+ //# sourceMappingURL=get-keyword.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-keyword.js","sourceRoot":"","sources":["../../src/tools/get-keyword.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type Database from 'better-sqlite3';
2
+ import { z } from 'zod';
3
+ export declare const GetMatchupInput: z.ZodObject<{
4
+ archetype_a: z.ZodString;
5
+ archetype_b: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ archetype_a: string;
8
+ archetype_b: string;
9
+ }, {
10
+ archetype_a: string;
11
+ archetype_b: string;
12
+ }>;
13
+ export type GetMatchupInputType = z.infer<typeof GetMatchupInput>;
14
+ export interface MatchupInfo {
15
+ archetype_a: string;
16
+ archetype_b: string;
17
+ favoured: string;
18
+ reasoning: string;
19
+ key_tension: string;
20
+ archetype_a_priority: string;
21
+ archetype_b_priority: string;
22
+ }
23
+ export type GetMatchupResult = {
24
+ found: true;
25
+ matchup: MatchupInfo;
26
+ } | {
27
+ found: false;
28
+ message: string;
29
+ suggestions?: string[];
30
+ };
31
+ export declare function getMatchup(db: Database.Database, input: GetMatchupInputType): GetMatchupResult;
32
+ //# sourceMappingURL=get-matchup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-matchup.d.ts","sourceRoot":"","sources":["../../src/tools/get-matchup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,eAAe;;;;;;;;;EAG1B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIlE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAI9D,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,mBAAmB,GACzB,gBAAgB,CAsClB"}
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ // --- Input Schema ---
3
+ export const GetMatchupInput = z.object({
4
+ archetype_a: z.string().describe('First archetype name (e.g. "aggro", "control")'),
5
+ archetype_b: z.string().describe('Second archetype name (e.g. "combo", "midrange")'),
6
+ });
7
+ // --- Handler ---
8
+ export function getMatchup(db, input) {
9
+ // Check both orderings since the table stores one direction
10
+ const row = db
11
+ .prepare(`SELECT * FROM matchup_framework WHERE
12
+ (LOWER(archetype_a) = LOWER(?) AND LOWER(archetype_b) = LOWER(?))
13
+ OR
14
+ (LOWER(archetype_a) = LOWER(?) AND LOWER(archetype_b) = LOWER(?))`)
15
+ .get(input.archetype_a, input.archetype_b, input.archetype_b, input.archetype_a);
16
+ if (row) {
17
+ return {
18
+ found: true,
19
+ matchup: {
20
+ archetype_a: row.archetype_a,
21
+ archetype_b: row.archetype_b,
22
+ favoured: row.favoured,
23
+ reasoning: row.reasoning,
24
+ key_tension: row.key_tension,
25
+ archetype_a_priority: row.archetype_a_priority,
26
+ archetype_b_priority: row.archetype_b_priority,
27
+ },
28
+ };
29
+ }
30
+ // Not found — suggest available archetypes
31
+ const archetypes = db
32
+ .prepare('SELECT DISTINCT archetype_a FROM matchup_framework UNION SELECT DISTINCT archetype_b FROM matchup_framework')
33
+ .all();
34
+ const availableNames = archetypes.map((a) => a.archetype_a);
35
+ return {
36
+ found: false,
37
+ message: `No matchup found for "${input.archetype_a}" vs "${input.archetype_b}".`,
38
+ suggestions: availableNames.length > 0 ? availableNames : undefined,
39
+ };
40
+ }
41
+ //# sourceMappingURL=get-matchup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-matchup.js","sourceRoot":"","sources":["../../src/tools/get-matchup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,uBAAuB;AAEvB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;IAClF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;CACrF,CAAC,CAAC;AAoBH,kBAAkB;AAElB,MAAM,UAAU,UAAU,CACxB,EAAqB,EACrB,KAA0B;IAE1B,4DAA4D;IAC5D,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CACN;;;0EAGoE,CACrE;SACA,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAA4B,CAAC;IAE9G,IAAI,GAAG,EAAE,CAAC;QACR,OAAO;YACL,KAAK,EAAE,IAAI;YACX,OAAO,EAAE;gBACP,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;gBAC9C,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;aAC/C;SACF,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,MAAM,UAAU,GAAG,EAAE;SAClB,OAAO,CAAC,6GAA6G,CAAC;SACtH,GAAG,EAAoC,CAAC;IAE3C,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAE5D,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,yBAAyB,KAAK,CAAC,WAAW,SAAS,KAAK,CAAC,WAAW,IAAI;QACjF,WAAW,EAAE,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type Database from 'better-sqlite3';
2
+ import { z } from 'zod';
3
+ import type { SearchCardsResult } from '../format.js';
4
+ export declare const SearchCardsInput: z.ZodObject<{
5
+ query: z.ZodOptional<z.ZodString>;
6
+ player_class: z.ZodOptional<z.ZodString>;
7
+ mana_cost: z.ZodOptional<z.ZodNumber>;
8
+ cost_op: z.ZodDefault<z.ZodOptional<z.ZodEnum<["eq", "lt", "lte", "gt", "gte"]>>>;
9
+ type: z.ZodOptional<z.ZodString>;
10
+ rarity: z.ZodOptional<z.ZodString>;
11
+ card_set: z.ZodOptional<z.ZodString>;
12
+ keyword: z.ZodOptional<z.ZodString>;
13
+ race: z.ZodOptional<z.ZodString>;
14
+ collectible_only: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15
+ limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ cost_op: "eq" | "lt" | "lte" | "gt" | "gte";
18
+ collectible_only: boolean;
19
+ limit: number;
20
+ player_class?: string | undefined;
21
+ type?: string | undefined;
22
+ keyword?: string | undefined;
23
+ query?: string | undefined;
24
+ mana_cost?: number | undefined;
25
+ rarity?: string | undefined;
26
+ card_set?: string | undefined;
27
+ race?: string | undefined;
28
+ }, {
29
+ player_class?: string | undefined;
30
+ type?: string | undefined;
31
+ keyword?: string | undefined;
32
+ query?: string | undefined;
33
+ mana_cost?: number | undefined;
34
+ cost_op?: "eq" | "lt" | "lte" | "gt" | "gte" | undefined;
35
+ rarity?: string | undefined;
36
+ card_set?: string | undefined;
37
+ race?: string | undefined;
38
+ collectible_only?: boolean | undefined;
39
+ limit?: number | undefined;
40
+ }>;
41
+ export type SearchCardsInputType = z.infer<typeof SearchCardsInput>;
42
+ export declare function searchCards(db: Database.Database, input: SearchCardsInputType): SearchCardsResult;
43
+ //# sourceMappingURL=search-cards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-cards.d.ts","sourceRoot":"","sources":["../../src/tools/search-cards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAe,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAInE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkD3B,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAgCpE,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,oBAAoB,GAC1B,iBAAiB,CAyGnB"}
@@ -0,0 +1,167 @@
1
+ import { z } from 'zod';
2
+ // --- Input Schema ---
3
+ export const SearchCardsInput = z.object({
4
+ query: z
5
+ .string()
6
+ .optional()
7
+ .describe('Free-text search across card name and text (uses FTS5)'),
8
+ player_class: z
9
+ .string()
10
+ .optional()
11
+ .describe('Filter by class (e.g. MAGE, WARRIOR, NEUTRAL)'),
12
+ mana_cost: z
13
+ .number()
14
+ .optional()
15
+ .describe('Filter by mana cost (combine with cost_op for range queries)'),
16
+ cost_op: z
17
+ .enum(['eq', 'lt', 'lte', 'gt', 'gte'])
18
+ .optional()
19
+ .default('eq')
20
+ .describe('Cost comparison operator: eq, lt, lte, gt, gte (default: eq)'),
21
+ type: z
22
+ .string()
23
+ .optional()
24
+ .describe('Filter by card type: MINION, SPELL, WEAPON, HERO, LOCATION'),
25
+ rarity: z
26
+ .string()
27
+ .optional()
28
+ .describe('Filter by rarity: FREE, COMMON, RARE, EPIC, LEGENDARY'),
29
+ card_set: z
30
+ .string()
31
+ .optional()
32
+ .describe('Filter by set code (e.g. CORE, CLASSIC, LOE)'),
33
+ keyword: z
34
+ .string()
35
+ .optional()
36
+ .describe('Filter by keyword in keywords JSON (e.g. BATTLECRY, TAUNT, CHARGE)'),
37
+ race: z
38
+ .string()
39
+ .optional()
40
+ .describe('Filter by minion race/tribe (e.g. BEAST, DRAGON, MURLOC)'),
41
+ collectible_only: z
42
+ .boolean()
43
+ .optional()
44
+ .default(true)
45
+ .describe('Only return collectible cards (default: true)'),
46
+ limit: z
47
+ .number()
48
+ .min(1)
49
+ .max(50)
50
+ .optional()
51
+ .default(25)
52
+ .describe('Max results to return, 1-50 (default: 25)'),
53
+ });
54
+ // --- Cost operator mapping ---
55
+ const COST_OPS = {
56
+ eq: '=',
57
+ lt: '<',
58
+ lte: '<=',
59
+ gt: '>',
60
+ gte: '>=',
61
+ };
62
+ // --- Helper: parse keywords JSON ---
63
+ function parseKeywords(raw) {
64
+ if (!raw)
65
+ return [];
66
+ try {
67
+ return JSON.parse(raw);
68
+ }
69
+ catch {
70
+ return [];
71
+ }
72
+ }
73
+ // --- Helper: first line preview ---
74
+ function textPreview(text) {
75
+ if (!text)
76
+ return null;
77
+ return text.split('\n')[0];
78
+ }
79
+ // --- Handler ---
80
+ export function searchCards(db, input) {
81
+ const params = [];
82
+ const conditions = [];
83
+ const useFts = !!input.query;
84
+ // Collectible filter
85
+ if (input.collectible_only !== false) {
86
+ conditions.push('c.collectible = 1');
87
+ }
88
+ // Class filter
89
+ if (input.player_class) {
90
+ conditions.push('UPPER(c.player_class) = UPPER(?)');
91
+ params.push(input.player_class);
92
+ }
93
+ // Cost filter
94
+ if (input.mana_cost != null) {
95
+ const op = COST_OPS[input.cost_op ?? 'eq'] ?? '=';
96
+ conditions.push(`c.mana_cost ${op} ?`);
97
+ params.push(input.mana_cost);
98
+ }
99
+ // Type filter
100
+ if (input.type) {
101
+ conditions.push('UPPER(c.type) = UPPER(?)');
102
+ params.push(input.type);
103
+ }
104
+ // Rarity filter
105
+ if (input.rarity) {
106
+ conditions.push('UPPER(c.rarity) = UPPER(?)');
107
+ params.push(input.rarity);
108
+ }
109
+ // Set filter
110
+ if (input.card_set) {
111
+ conditions.push('UPPER(c.card_set) = UPPER(?)');
112
+ params.push(input.card_set);
113
+ }
114
+ // Keyword filter (search in JSON string)
115
+ if (input.keyword) {
116
+ conditions.push("c.keywords LIKE '%' || ? || '%'");
117
+ params.push(input.keyword);
118
+ }
119
+ // Race filter
120
+ if (input.race) {
121
+ conditions.push('UPPER(c.race) = UPPER(?)');
122
+ params.push(input.race);
123
+ }
124
+ const limit = input.limit ?? 25;
125
+ let sql;
126
+ const allParams = [];
127
+ if (useFts) {
128
+ // FTS5 query
129
+ allParams.push(input.query);
130
+ allParams.push(...params);
131
+ allParams.push(limit);
132
+ const whereClause = conditions.length > 0 ? ' AND ' + conditions.join(' AND ') : '';
133
+ sql = `
134
+ SELECT c.* FROM cards_fts fts
135
+ JOIN cards c ON c.rowid = fts.rowid
136
+ WHERE cards_fts MATCH ?${whereClause}
137
+ ORDER BY fts.rank
138
+ LIMIT ?
139
+ `;
140
+ }
141
+ else {
142
+ // Regular query
143
+ allParams.push(...params);
144
+ allParams.push(limit);
145
+ const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
146
+ sql = `
147
+ SELECT c.* FROM cards c
148
+ ${whereClause}
149
+ ORDER BY c.name
150
+ LIMIT ?
151
+ `;
152
+ }
153
+ const rows = db.prepare(sql).all(...allParams);
154
+ const cards = rows.map((row) => ({
155
+ name: row.name,
156
+ mana_cost: row.mana_cost,
157
+ type: row.type,
158
+ player_class: row.player_class,
159
+ rarity: row.rarity,
160
+ text: textPreview(row.text),
161
+ attack: row.attack,
162
+ health: row.health,
163
+ keywords: parseKeywords(row.keywords),
164
+ }));
165
+ return { cards, total: cards.length };
166
+ }
167
+ //# sourceMappingURL=search-cards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-cards.js","sourceRoot":"","sources":["../../src/tools/search-cards.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "hearthstone-oracle",
3
+ "version": "0.1.0",
4
+ "description": "Hearthstone MCP server with card search, deck analysis, and strategy coaching",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "dist/server.js",
8
+ "bin": {
9
+ "hearthstone-oracle": "dist/server.js"
10
+ },
11
+ "files": [
12
+ "dist/**/*.js",
13
+ "dist/**/*.d.ts",
14
+ "dist/**/*.js.map",
15
+ "dist/**/*.d.ts.map",
16
+ "dist/data/schema.sql"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc && cp src/data/schema.sql dist/data/schema.sql && chmod +x dist/server.js",
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "start": "node dist/server.js",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.12.1",
27
+ "better-sqlite3": "^12.8.0",
28
+ "deckstrings": "^2.2.0",
29
+ "zod": "^3.24.2"
30
+ },
31
+ "devDependencies": {
32
+ "@types/better-sqlite3": "^7.6.13",
33
+ "@types/node": "^22.13.10",
34
+ "typescript": "^5.8.2",
35
+ "vitest": "^3.1.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "mcpName": "io.github.gregario/hearthstone-oracle",
41
+ "keywords": [
42
+ "mcp",
43
+ "hearthstone",
44
+ "card-game",
45
+ "strategy",
46
+ "deck-analysis",
47
+ "claude",
48
+ "ai"
49
+ ]
50
+ }