@dizzlkheinz/ynab-mcpb 0.16.1 → 0.17.1

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 (169) hide show
  1. package/.env.example +33 -33
  2. package/.github/workflows/ci-tests.yml +45 -45
  3. package/.github/workflows/claude-code-review.yml +57 -57
  4. package/.github/workflows/claude.yml +50 -50
  5. package/.github/workflows/full-integration.yml +22 -22
  6. package/.github/workflows/publish.yml +11 -2
  7. package/CLAUDE.md +33 -47
  8. package/README.md +8 -10
  9. package/dist/bundle/index.cjs +54 -54
  10. package/dist/server/YNABMCPServer.d.ts +120 -54
  11. package/dist/server/YNABMCPServer.js +28 -381
  12. package/dist/server/config.d.ts +2 -0
  13. package/dist/server/config.js +1 -0
  14. package/dist/server/securityMiddleware.d.ts +37 -8
  15. package/dist/tools/accountTools.d.ts +2 -0
  16. package/dist/tools/accountTools.js +45 -0
  17. package/dist/tools/adapters.d.ts +12 -0
  18. package/dist/tools/adapters.js +25 -0
  19. package/dist/tools/budgetTools.d.ts +2 -0
  20. package/dist/tools/budgetTools.js +30 -0
  21. package/dist/tools/categoryTools.d.ts +2 -0
  22. package/dist/tools/categoryTools.js +45 -0
  23. package/dist/tools/monthTools.d.ts +2 -0
  24. package/dist/tools/monthTools.js +32 -0
  25. package/dist/tools/payeeTools.d.ts +2 -0
  26. package/dist/tools/payeeTools.js +32 -0
  27. package/dist/tools/reconciliation/index.d.ts +2 -0
  28. package/dist/tools/reconciliation/index.js +33 -0
  29. package/dist/tools/schemas/common.d.ts +3 -0
  30. package/dist/tools/schemas/common.js +3 -0
  31. package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
  32. package/dist/tools/schemas/outputs/index.d.ts +2 -2
  33. package/dist/tools/schemas/outputs/index.js +2 -2
  34. package/dist/tools/schemas/outputs/utilityOutputs.d.ts +0 -15
  35. package/dist/tools/schemas/outputs/utilityOutputs.js +0 -9
  36. package/dist/tools/transactionTools.d.ts +2 -0
  37. package/dist/tools/transactionTools.js +124 -0
  38. package/dist/tools/utilityTools.d.ts +2 -7
  39. package/dist/tools/utilityTools.js +19 -38
  40. package/dist/types/index.d.ts +1 -0
  41. package/dist/types/toolRegistration.d.ts +27 -0
  42. package/dist/types/toolRegistration.js +1 -0
  43. package/docs/maintainers/npm-publishing.md +27 -0
  44. package/docs/reference/API.md +15 -70
  45. package/docs/technical/reconciliation-system-architecture.md +2251 -2251
  46. package/package.json +6 -6
  47. package/scripts/analyze-bundle.mjs +41 -41
  48. package/scripts/generate-mcpb.ps1 +95 -95
  49. package/scripts/run-domain-integration-tests.js +4 -1
  50. package/scripts/watch-and-restart.ps1 +49 -49
  51. package/src/__tests__/comprehensive.integration.test.ts +0 -28
  52. package/src/__tests__/performance.test.ts +4 -12
  53. package/src/__tests__/setup.ts +45 -14
  54. package/src/__tests__/workflows.e2e.test.ts +1 -51
  55. package/src/server/YNABMCPServer.ts +33 -519
  56. package/src/server/__tests__/YNABMCPServer.test.ts +0 -1
  57. package/src/server/__tests__/toolRegistration.test.ts +236 -0
  58. package/src/server/config.ts +1 -0
  59. package/src/tools/__tests__/adapters.test.ts +113 -0
  60. package/src/tools/__tests__/transactionTools.integration.test.ts +63 -3
  61. package/src/tools/__tests__/utilityTools.integration.test.ts +1 -85
  62. package/src/tools/__tests__/utilityTools.test.ts +1 -123
  63. package/src/tools/accountTools.ts +53 -0
  64. package/src/tools/adapters.ts +74 -0
  65. package/src/tools/budgetTools.ts +37 -0
  66. package/src/tools/categoryTools.ts +53 -0
  67. package/src/tools/monthTools.ts +39 -0
  68. package/src/tools/payeeTools.ts +39 -0
  69. package/src/tools/reconciliation/index.ts +45 -0
  70. package/src/tools/schemas/common.ts +18 -0
  71. package/src/tools/schemas/outputs/index.ts +0 -3
  72. package/src/tools/schemas/outputs/utilityOutputs.ts +2 -43
  73. package/src/tools/toolCategories.ts +0 -1
  74. package/src/tools/transactionTools.ts +140 -0
  75. package/src/tools/utilityTools.ts +24 -55
  76. package/src/types/index.ts +3 -0
  77. package/src/types/toolRegistration.ts +88 -0
  78. package/vitest.config.ts +2 -1
  79. package/.chunkhound.json +0 -11
  80. package/.code/agents/01a13ef4-3f23-4f52-b33b-3585b73cfa60/error.txt +0 -3
  81. package/.code/agents/084fd32f-e298-4728-9103-a78d7dc39613/error.txt +0 -3
  82. package/.code/agents/0fed51e1-a943-4b97-a2a8-a6f0f27c844d/status.txt +0 -1
  83. package/.code/agents/1059b6bd-5ccd-4d83-a12c-7c9d89137399/error.txt +0 -5
  84. package/.code/agents/110/exec-call_F9BDNG7JfxKkq7Vc8ESAvdft.txt +0 -1569
  85. package/.code/agents/11ebcef3-b13f-4e44-ad80-d94a866804b7/error.txt +0 -3
  86. package/.code/agents/1398/exec-call_CjItcWMU1G6JoPshX62QvpaR.txt +0 -2832
  87. package/.code/agents/1398/exec-call_SUVq2ivmONQ5LMCmd7ngmOqr.txt +0 -2709
  88. package/.code/agents/1398/exec-call_SdNY4NOffdcC5pRYjVXHjPCK.txt +0 -2832
  89. package/.code/agents/1398/exec-call_qblJo9et1gsFFB63TtLOiji2.txt +0 -2832
  90. package/.code/agents/1398/exec-call_zaRrzlGz7GJcNzVfkAmML7Zg.txt +0 -2709
  91. package/.code/agents/171834fd-5905-42fc-bbcc-2c755145b0fc/status.txt +0 -1
  92. package/.code/agents/1724/exec-call_HvHQe0w5CCG3T7Q3ULT6MO3g.txt +0 -5217
  93. package/.code/agents/1724/exec-call_QwUNESVzfxxk78K1frh1Vahb.txt +0 -2594
  94. package/.code/agents/1724/exec-call_aJ1Xwz71XmIpD4SBxSHERzLe.txt +0 -2594
  95. package/.code/agents/1d7d7ab7-7473-4b69-8b97-6e914f56056a/result.txt +0 -231
  96. package/.code/agents/210/exec-call_0tQCsKNJ1WTuIchb8wlcFJpW.txt +0 -2590
  97. package/.code/agents/210/exec-call_8ZlY9cUc8Ft1twi4ch8UJ6IN.txt +0 -5195
  98. package/.code/agents/2188/exec-call_5HqayBxIteJtoI8oPTiLWgvJ.txt +0 -286
  99. package/.code/agents/2188/exec-call_XRbBKBq3adZe6dcppAvQtM7G.txt +0 -218
  100. package/.code/agents/2188/exec-call_ehA0SjpYtrUi6GJXmibLjp4i.txt +0 -180
  101. package/.code/agents/21902821-ecaf-4759-bb9d-222b90921af5/error.txt +0 -3
  102. package/.code/agents/232073be-aa0e-46da-b478-5b64dbf03cf5/status.txt +0 -1
  103. package/.code/agents/234ff534-2336-4771-a8d9-aa04421a63be/result.txt +0 -747
  104. package/.code/agents/253e2695-dc36-4022-b436-27655e0fc6c7/status.txt +0 -1
  105. package/.code/agents/2583/exec-call_M59I4eDjpjlBIWBiSxyS0YlJ.txt +0 -2594
  106. package/.code/agents/2583/exec-call_usLRGh7OhVHtsRBL4iUwRhjq.txt +0 -2594
  107. package/.code/agents/292aa3ff-dbab-470f-97c9-e7e8fd65e0db/result.txt +0 -144
  108. package/.code/agents/3134/exec-call_IgCAMGx19lWfuo8zfYIt5FFC.txt +0 -416
  109. package/.code/agents/3134/exec-call_IxvLR2Oo7kba2QTsI1gHVko8.txt +0 -2590
  110. package/.code/agents/3134/exec-call_jYvc8hksZChSiysbzKjl2ZbB.txt +0 -2590
  111. package/.code/agents/329/exec-call_4QdP3SfSO7HGPCwVcqZIth6s.txt +0 -2590
  112. package/.code/agents/472/exec-call_4AxzEEcWwkKhpqRB3bE8Ha4L.txt +0 -790
  113. package/.code/agents/472/exec-call_CB3LPYQA8QIZRi8I6kj4J17A.txt +0 -766
  114. package/.code/agents/472/exec-call_YeoUWvaFoktay2nqVUsa9KKX.txt +0 -790
  115. package/.code/agents/472/exec-call_jPWgKVquBBXTg0T3Lks5ZfkK.txt +0 -2594
  116. package/.code/agents/472/exec-call_qBkvunpGBDEHph2jPmTwtcsb.txt +0 -1000
  117. package/.code/agents/472/exec-call_v0ffRV1p0kTckBmJPzzHAEy0.txt +0 -3489
  118. package/.code/agents/472/exec-call_xAX5FXqWIlk02d9WubHbHWh8.txt +0 -766
  119. package/.code/agents/5346/exec-call_9q0muXUuLaucwEqI51Pt7idT.txt +0 -2594
  120. package/.code/agents/5346/exec-call_B2el3B79rVkq9LhWTI2VYlz7.txt +0 -2456
  121. package/.code/agents/5346/exec-call_BfX08f02qkZI9uJD5dvCvuoj.txt +0 -2594
  122. package/.code/agents/543328d0-61d6-4fd1-a723-bb168656e2e2/error.txt +0 -18
  123. package/.code/agents/5580c02c-1383-4d18-9cbd-cc8a06e3408d/result.txt +0 -48
  124. package/.code/agents/60ce1a22-5126-44b2-b977-1d5b56142a7b/status.txt +0 -1
  125. package/.code/agents/6215d9db-7fa9-4429-aeec-3835c3212291/error.txt +0 -1
  126. package/.code/agents/6743db55-30e5-4b4e-9366-a8214fc7f714/error.txt +0 -1
  127. package/.code/agents/6bf9591b-b9c9-422c-b0a5-e968c7d8422a/status.txt +0 -1
  128. package/.code/agents/7/exec-call_eww3GfdEiJZx61sJEQ9wNmt3.txt +0 -1271
  129. package/.code/agents/70/exec-call_owUtDMYiVgqDf8vsz1i32PFf.txt +0 -1570
  130. package/.code/agents/8/exec-call_UtrjAcLbhYLatxR4O97fZgnm.txt +0 -2590
  131. package/.code/agents/82490bc9-f34e-4b1b-8a8e-bccc2e6254f5/error.txt +0 -3
  132. package/.code/agents/841/exec-call_7nTNhSBCNjTDUIJv7py6CepO.txt +0 -3299
  133. package/.code/agents/841/exec-call_TLI0yUdUijuUAvI4o3DXEvHO.txt +0 -3299
  134. package/.code/agents/9/exec-call_XaABQT1hIlRpnKZ2uyBMWsTC.txt +0 -1882
  135. package/.code/agents/941/exec-call_GuGHRx7NNXWIDAnxUG2NEWPa.txt +0 -2594
  136. package/.code/agents/95d9fbab-19a2-48af-83f9-c792566a347f/error.txt +0 -1
  137. package/.code/agents/b0098cb8-cb32-4ada-9bc4-37c587518896/result.txt +0 -170
  138. package/.code/agents/b4fe59a4-81df-42e2-a112-0153e504faca/error.txt +0 -1
  139. package/.code/agents/bf4ce152-f623-49d7-aa52-c18631625c3c/error.txt +0 -3
  140. package/.code/agents/d7d1db75-d7eb-468e-adea-4ef4d916d187/status.txt +0 -1
  141. package/.code/agents/e2baa9c8-bac3-49e3-a39d-024333e6a990/status.txt +0 -1
  142. package/.code/agents/e350b8c3-8483-408c-b2bb-94515f492a11/error.txt +0 -3
  143. package/.code/agents/e63f9919-719f-4ad0-bccf-01b1a596e1e9/status.txt +0 -1
  144. package/.code/agents/e71695a8-3044-478d-8f12-ed13d02884c7/status.txt +0 -1
  145. package/.code/agents/f95b7464-3e25-4897-b153-c8dfd63fd605/error.txt +0 -5
  146. package/.code/agents/fa3c5ddf-cdf7-47a2-930a-b806c6363689/status.txt +0 -1
  147. package/.github/workflows/pr-description-check.yml +0 -88
  148. package/AGENTS.md +0 -36
  149. package/NUL +0 -1
  150. package/docs/README.md +0 -72
  151. package/docs/getting-started/CONFIGURATION.md +0 -175
  152. package/docs/getting-started/INSTALLATION.md +0 -333
  153. package/docs/getting-started/QUICKSTART.md +0 -282
  154. package/docs/guides/ARCHITECTURE.md +0 -533
  155. package/docs/guides/DEPLOYMENT.md +0 -189
  156. package/docs/guides/INTEGRATION_TESTING.md +0 -730
  157. package/docs/guides/TESTING.md +0 -591
  158. package/docs/reconciliation-flow.md +0 -83
  159. package/docs/reference/EXAMPLES.md +0 -946
  160. package/docs/reference/TOOLS.md +0 -348
  161. package/docs/reference/TROUBLESHOOTING.md +0 -481
  162. package/package.json.tmp +0 -105
  163. package/temp-recon.ts +0 -126
  164. package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_09-04-53.json +0 -23
  165. package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_10-37-42.json +0 -23
  166. package/test-exports/ynab_account_e9ddc2a6_minimal_4items_2025-11-19_09-02-09.json +0 -44
  167. package/test-exports/ynab_account_e9ddc2a6_minimal_6items_2025-11-19_10-37-52.json +0 -58
  168. package/test-exports/ynab_since_2025-10-16_account_53298e13_238items_2025-11-28_13-46-20.json +0 -3662
  169. package/test-exports/ynab_since_2025-11-01_account_4c18e9f0_minimal_14items_2025-11-16_10-07-10.json +0 -115
@@ -1,20 +1,11 @@
1
1
  import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
2
  import * as ynab from 'ynab';
3
- import { z } from 'zod/v4';
4
- import { withToolErrorHandling } from '../types/index.js';
5
3
  import { responseFormatter } from '../server/responseFormatter.js';
6
-
7
- /**
8
- * Schema for ynab:convert_amount tool parameters
9
- */
10
- export const ConvertAmountSchema = z
11
- .object({
12
- amount: z.number().finite(),
13
- to_milliunits: z.boolean(),
14
- })
15
- .strict();
16
-
17
- export type ConvertAmountParams = z.infer<typeof ConvertAmountSchema>;
4
+ import { withToolErrorHandling } from '../types/index.js';
5
+ import { createAdapters } from './adapters.js';
6
+ import { emptyObjectSchema } from './schemas/common.js';
7
+ import { ToolAnnotationPresets } from './toolCategories.js';
8
+ import type { ToolFactory } from '../types/toolRegistration.js';
18
9
 
19
10
  /**
20
11
  * Handles the ynab:get_user tool call
@@ -45,46 +36,24 @@ export async function handleGetUser(ynabAPI: ynab.API): Promise<CallToolResult>
45
36
  }
46
37
 
47
38
  /**
48
- * Handles the ynab:convert_amount tool call
49
- * Converts between dollars and milliunits with integer arithmetic for precision
39
+ * Registers utility tools (get_user) using the shared factory pattern.
40
+ *
41
+ * Note: convert_amount was removed because all tool responses already return
42
+ * amounts in dollars (converted from YNAB milliunits internally).
50
43
  */
51
- export async function handleConvertAmount(params: ConvertAmountParams): Promise<CallToolResult> {
52
- return await withToolErrorHandling(
53
- async () => {
54
- const { amount, to_milliunits } = params;
55
-
56
- let result: number;
57
- let description: string;
58
-
59
- if (to_milliunits) {
60
- // Convert from dollars to milliunits
61
- // Use integer arithmetic to avoid floating-point precision issues
62
- result = Math.round(amount * 1000);
63
- description = `$${amount.toFixed(2)} = ${result} milliunits`;
64
- } else {
65
- // Convert from milliunits to dollars
66
- // Assume input amount is in milliunits
67
- result = amount / 1000;
68
- description = `${amount} milliunits = $${result.toFixed(2)}`;
69
- }
70
-
71
- return {
72
- content: [
73
- {
74
- type: 'text',
75
- text: responseFormatter.format({
76
- conversion: {
77
- original_amount: amount,
78
- converted_amount: result,
79
- to_milliunits,
80
- description,
81
- },
82
- }),
83
- },
84
- ],
85
- };
44
+ export const registerUtilityTools: ToolFactory = (registry, context) => {
45
+ const { adaptNoInput } = createAdapters(context);
46
+
47
+ registry.register({
48
+ name: 'get_user',
49
+ description: 'Get information about the authenticated user',
50
+ inputSchema: emptyObjectSchema,
51
+ handler: adaptNoInput(handleGetUser),
52
+ metadata: {
53
+ annotations: {
54
+ ...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
55
+ title: 'YNAB: Get User Information',
56
+ },
86
57
  },
87
- 'ynab:convert_amount',
88
- 'converting amount',
89
- );
90
- }
58
+ });
59
+ };
@@ -65,3 +65,6 @@ export type { MCPToolAnnotations } from './toolAnnotations.js';
65
65
 
66
66
  // Re-export tool registry types for convenience
67
67
  export type { ToolDefinition } from '../server/toolRegistry.js';
68
+
69
+ // Re-export tool registration factory types
70
+ export type { ToolContext, ToolFactory, BudgetIdResolverFactory } from './toolRegistration.js';
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @fileoverview Type definitions for the tool factory registration pattern.
3
+ * Provides ToolContext for dependency injection and typed handler signatures
4
+ * used by domain-specific tool factory functions.
5
+ * @module types/toolRegistration
6
+ */
7
+
8
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
9
+ import * as ynab from 'ynab';
10
+ import type {
11
+ ToolRegistry,
12
+ ToolExecutionPayload,
13
+ DefaultArgumentResolver,
14
+ } from '../server/toolRegistry.js';
15
+ import type { DeltaFetcher } from '../tools/deltaFetcher.js';
16
+ import type { DeltaCache } from '../server/deltaCache.js';
17
+ import type { ServerKnowledgeStore } from '../server/serverKnowledgeStore.js';
18
+ import type { DiagnosticManager } from '../server/diagnostics.js';
19
+ import type { CacheManager } from '../server/cacheManager.js';
20
+
21
+ /**
22
+ * Context object passed to tool factory functions. Contains the dependencies
23
+ * required by tool adapters and handlers.
24
+ *
25
+ * @stable This interface is part of the public tool registration contract.
26
+ * Changes to this interface may affect all domain tool factories.
27
+ */
28
+ export interface ToolContext {
29
+ ynabAPI: ynab.API;
30
+ deltaFetcher: DeltaFetcher;
31
+ deltaCache: DeltaCache;
32
+ serverKnowledgeStore: ServerKnowledgeStore;
33
+ getDefaultBudgetId: () => string | undefined;
34
+ setDefaultBudget: (budgetId: string) => void;
35
+ cacheManager: CacheManager;
36
+ diagnosticManager?: DiagnosticManager;
37
+ }
38
+
39
+ /**
40
+ * Factory function signature for registering a domain's tools.
41
+ */
42
+ export type ToolFactory = (registry: ToolRegistry, context: ToolContext) => void;
43
+
44
+ /**
45
+ * Common adapter signature used within tool factories.
46
+ */
47
+ export type Adapter<TInput extends Record<string, unknown>> = (
48
+ payload: ToolExecutionPayload<TInput>,
49
+ ) => Promise<CallToolResult>;
50
+
51
+ /**
52
+ * Generic handler signature used by adapter helpers.
53
+ */
54
+ export type Handler<TInput extends Record<string, unknown>> = (
55
+ api: ynab.API,
56
+ params: TInput,
57
+ ) => Promise<CallToolResult>;
58
+
59
+ /**
60
+ * Handler signature for operations that require delta fetching.
61
+ */
62
+ export type DeltaHandler<TInput extends Record<string, unknown>> = (
63
+ api: ynab.API,
64
+ deltaFetcher: DeltaFetcher,
65
+ params: TInput,
66
+ ) => Promise<CallToolResult>;
67
+
68
+ /**
69
+ * Handler signature for write operations that update caches and knowledge stores.
70
+ */
71
+ export type WriteHandler<TInput extends Record<string, unknown>> = (
72
+ api: ynab.API,
73
+ deltaCache: DeltaCache,
74
+ serverKnowledgeStore: ServerKnowledgeStore,
75
+ params: TInput,
76
+ ) => Promise<CallToolResult>;
77
+
78
+ /**
79
+ * Handler signature for tools that do not accept input parameters.
80
+ */
81
+ export type NoInputHandler = (api: ynab.API) => Promise<CallToolResult>;
82
+
83
+ /**
84
+ * Helper type for default argument resolver factories.
85
+ */
86
+ export type BudgetIdResolverFactory = <
87
+ TInput extends { budget_id?: string | undefined },
88
+ >() => DefaultArgumentResolver<TInput>;
package/vitest.config.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
3
  const integrationFiles = ['src/**/*.integration.test.ts'];
4
+ const isVerbose = !!process.env['VERBOSE_TESTS'];
4
5
 
5
6
  export default defineConfig({
6
7
  test: {
@@ -83,7 +84,7 @@ export default defineConfig({
83
84
  },
84
85
  },
85
86
  },
86
- reporters: ['verbose', 'html', './vitest-reporters/split-json-reporter.ts'],
87
+ reporters: [isVerbose ? 'verbose' : 'dot', 'html', './vitest-reporters/split-json-reporter.ts'],
87
88
  outputFile: {
88
89
  html: './test-results/index.html',
89
90
  },
package/.chunkhound.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "embedding": {
3
- "provider": "voyageai",
4
- "model": "voyage-3.5",
5
- "api_key": "pa-Q1WewxKAEUA6QeYTmreQmY11ufEk9mKIK0DfoqqZhV6",
6
- "rerank_model": "rerank-2.5"
7
- },
8
- "llm": {
9
- "provider": "claude-code-cli"
10
- }
11
- }
@@ -1,3 +0,0 @@
1
- Command failed: Error loading configuration: config profile `From the repo root, list top-level files and directories using ls or dir, then exit. No file writes or edits.
2
-
3
- [Running in read-only mode - no modifications allowed]` not found
@@ -1,3 +0,0 @@
1
- Command failed: Error loading configuration: config profile `From the repo root, just run `pwd` and then exit. Do not modify any files.
2
-
3
- [Running in read-only mode - no modifications allowed]` not found
@@ -1 +0,0 @@
1
- Agent cancelled
@@ -1,5 +0,0 @@
1
- Command failed: ParserError: 
2
- Line |
3
-  5 |  [Running in read-only mode - no modifications allowed]
4
-  |  ~
5
-  | Missing ] at end of attribute or type literal.