@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.
- package/.env.example +33 -33
- package/.github/workflows/ci-tests.yml +45 -45
- package/.github/workflows/claude-code-review.yml +57 -57
- package/.github/workflows/claude.yml +50 -50
- package/.github/workflows/full-integration.yml +22 -22
- package/.github/workflows/publish.yml +11 -2
- package/CLAUDE.md +33 -47
- package/README.md +8 -10
- package/dist/bundle/index.cjs +54 -54
- package/dist/server/YNABMCPServer.d.ts +120 -54
- package/dist/server/YNABMCPServer.js +28 -381
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.js +1 -0
- package/dist/server/securityMiddleware.d.ts +37 -8
- package/dist/tools/accountTools.d.ts +2 -0
- package/dist/tools/accountTools.js +45 -0
- package/dist/tools/adapters.d.ts +12 -0
- package/dist/tools/adapters.js +25 -0
- package/dist/tools/budgetTools.d.ts +2 -0
- package/dist/tools/budgetTools.js +30 -0
- package/dist/tools/categoryTools.d.ts +2 -0
- package/dist/tools/categoryTools.js +45 -0
- package/dist/tools/monthTools.d.ts +2 -0
- package/dist/tools/monthTools.js +32 -0
- package/dist/tools/payeeTools.d.ts +2 -0
- package/dist/tools/payeeTools.js +32 -0
- package/dist/tools/reconciliation/index.d.ts +2 -0
- package/dist/tools/reconciliation/index.js +33 -0
- package/dist/tools/schemas/common.d.ts +3 -0
- package/dist/tools/schemas/common.js +3 -0
- package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/index.d.ts +2 -2
- package/dist/tools/schemas/outputs/index.js +2 -2
- package/dist/tools/schemas/outputs/utilityOutputs.d.ts +0 -15
- package/dist/tools/schemas/outputs/utilityOutputs.js +0 -9
- package/dist/tools/transactionTools.d.ts +2 -0
- package/dist/tools/transactionTools.js +124 -0
- package/dist/tools/utilityTools.d.ts +2 -7
- package/dist/tools/utilityTools.js +19 -38
- package/dist/types/index.d.ts +1 -0
- package/dist/types/toolRegistration.d.ts +27 -0
- package/dist/types/toolRegistration.js +1 -0
- package/docs/maintainers/npm-publishing.md +27 -0
- package/docs/reference/API.md +15 -70
- package/docs/technical/reconciliation-system-architecture.md +2251 -2251
- package/package.json +6 -6
- package/scripts/analyze-bundle.mjs +41 -41
- package/scripts/generate-mcpb.ps1 +95 -95
- package/scripts/run-domain-integration-tests.js +4 -1
- package/scripts/watch-and-restart.ps1 +49 -49
- package/src/__tests__/comprehensive.integration.test.ts +0 -28
- package/src/__tests__/performance.test.ts +4 -12
- package/src/__tests__/setup.ts +45 -14
- package/src/__tests__/workflows.e2e.test.ts +1 -51
- package/src/server/YNABMCPServer.ts +33 -519
- package/src/server/__tests__/YNABMCPServer.test.ts +0 -1
- package/src/server/__tests__/toolRegistration.test.ts +236 -0
- package/src/server/config.ts +1 -0
- package/src/tools/__tests__/adapters.test.ts +113 -0
- package/src/tools/__tests__/transactionTools.integration.test.ts +63 -3
- package/src/tools/__tests__/utilityTools.integration.test.ts +1 -85
- package/src/tools/__tests__/utilityTools.test.ts +1 -123
- package/src/tools/accountTools.ts +53 -0
- package/src/tools/adapters.ts +74 -0
- package/src/tools/budgetTools.ts +37 -0
- package/src/tools/categoryTools.ts +53 -0
- package/src/tools/monthTools.ts +39 -0
- package/src/tools/payeeTools.ts +39 -0
- package/src/tools/reconciliation/index.ts +45 -0
- package/src/tools/schemas/common.ts +18 -0
- package/src/tools/schemas/outputs/index.ts +0 -3
- package/src/tools/schemas/outputs/utilityOutputs.ts +2 -43
- package/src/tools/toolCategories.ts +0 -1
- package/src/tools/transactionTools.ts +140 -0
- package/src/tools/utilityTools.ts +24 -55
- package/src/types/index.ts +3 -0
- package/src/types/toolRegistration.ts +88 -0
- package/vitest.config.ts +2 -1
- package/.chunkhound.json +0 -11
- package/.code/agents/01a13ef4-3f23-4f52-b33b-3585b73cfa60/error.txt +0 -3
- package/.code/agents/084fd32f-e298-4728-9103-a78d7dc39613/error.txt +0 -3
- package/.code/agents/0fed51e1-a943-4b97-a2a8-a6f0f27c844d/status.txt +0 -1
- package/.code/agents/1059b6bd-5ccd-4d83-a12c-7c9d89137399/error.txt +0 -5
- package/.code/agents/110/exec-call_F9BDNG7JfxKkq7Vc8ESAvdft.txt +0 -1569
- package/.code/agents/11ebcef3-b13f-4e44-ad80-d94a866804b7/error.txt +0 -3
- package/.code/agents/1398/exec-call_CjItcWMU1G6JoPshX62QvpaR.txt +0 -2832
- package/.code/agents/1398/exec-call_SUVq2ivmONQ5LMCmd7ngmOqr.txt +0 -2709
- package/.code/agents/1398/exec-call_SdNY4NOffdcC5pRYjVXHjPCK.txt +0 -2832
- package/.code/agents/1398/exec-call_qblJo9et1gsFFB63TtLOiji2.txt +0 -2832
- package/.code/agents/1398/exec-call_zaRrzlGz7GJcNzVfkAmML7Zg.txt +0 -2709
- package/.code/agents/171834fd-5905-42fc-bbcc-2c755145b0fc/status.txt +0 -1
- package/.code/agents/1724/exec-call_HvHQe0w5CCG3T7Q3ULT6MO3g.txt +0 -5217
- package/.code/agents/1724/exec-call_QwUNESVzfxxk78K1frh1Vahb.txt +0 -2594
- package/.code/agents/1724/exec-call_aJ1Xwz71XmIpD4SBxSHERzLe.txt +0 -2594
- package/.code/agents/1d7d7ab7-7473-4b69-8b97-6e914f56056a/result.txt +0 -231
- package/.code/agents/210/exec-call_0tQCsKNJ1WTuIchb8wlcFJpW.txt +0 -2590
- package/.code/agents/210/exec-call_8ZlY9cUc8Ft1twi4ch8UJ6IN.txt +0 -5195
- package/.code/agents/2188/exec-call_5HqayBxIteJtoI8oPTiLWgvJ.txt +0 -286
- package/.code/agents/2188/exec-call_XRbBKBq3adZe6dcppAvQtM7G.txt +0 -218
- package/.code/agents/2188/exec-call_ehA0SjpYtrUi6GJXmibLjp4i.txt +0 -180
- package/.code/agents/21902821-ecaf-4759-bb9d-222b90921af5/error.txt +0 -3
- package/.code/agents/232073be-aa0e-46da-b478-5b64dbf03cf5/status.txt +0 -1
- package/.code/agents/234ff534-2336-4771-a8d9-aa04421a63be/result.txt +0 -747
- package/.code/agents/253e2695-dc36-4022-b436-27655e0fc6c7/status.txt +0 -1
- package/.code/agents/2583/exec-call_M59I4eDjpjlBIWBiSxyS0YlJ.txt +0 -2594
- package/.code/agents/2583/exec-call_usLRGh7OhVHtsRBL4iUwRhjq.txt +0 -2594
- package/.code/agents/292aa3ff-dbab-470f-97c9-e7e8fd65e0db/result.txt +0 -144
- package/.code/agents/3134/exec-call_IgCAMGx19lWfuo8zfYIt5FFC.txt +0 -416
- package/.code/agents/3134/exec-call_IxvLR2Oo7kba2QTsI1gHVko8.txt +0 -2590
- package/.code/agents/3134/exec-call_jYvc8hksZChSiysbzKjl2ZbB.txt +0 -2590
- package/.code/agents/329/exec-call_4QdP3SfSO7HGPCwVcqZIth6s.txt +0 -2590
- package/.code/agents/472/exec-call_4AxzEEcWwkKhpqRB3bE8Ha4L.txt +0 -790
- package/.code/agents/472/exec-call_CB3LPYQA8QIZRi8I6kj4J17A.txt +0 -766
- package/.code/agents/472/exec-call_YeoUWvaFoktay2nqVUsa9KKX.txt +0 -790
- package/.code/agents/472/exec-call_jPWgKVquBBXTg0T3Lks5ZfkK.txt +0 -2594
- package/.code/agents/472/exec-call_qBkvunpGBDEHph2jPmTwtcsb.txt +0 -1000
- package/.code/agents/472/exec-call_v0ffRV1p0kTckBmJPzzHAEy0.txt +0 -3489
- package/.code/agents/472/exec-call_xAX5FXqWIlk02d9WubHbHWh8.txt +0 -766
- package/.code/agents/5346/exec-call_9q0muXUuLaucwEqI51Pt7idT.txt +0 -2594
- package/.code/agents/5346/exec-call_B2el3B79rVkq9LhWTI2VYlz7.txt +0 -2456
- package/.code/agents/5346/exec-call_BfX08f02qkZI9uJD5dvCvuoj.txt +0 -2594
- package/.code/agents/543328d0-61d6-4fd1-a723-bb168656e2e2/error.txt +0 -18
- package/.code/agents/5580c02c-1383-4d18-9cbd-cc8a06e3408d/result.txt +0 -48
- package/.code/agents/60ce1a22-5126-44b2-b977-1d5b56142a7b/status.txt +0 -1
- package/.code/agents/6215d9db-7fa9-4429-aeec-3835c3212291/error.txt +0 -1
- package/.code/agents/6743db55-30e5-4b4e-9366-a8214fc7f714/error.txt +0 -1
- package/.code/agents/6bf9591b-b9c9-422c-b0a5-e968c7d8422a/status.txt +0 -1
- package/.code/agents/7/exec-call_eww3GfdEiJZx61sJEQ9wNmt3.txt +0 -1271
- package/.code/agents/70/exec-call_owUtDMYiVgqDf8vsz1i32PFf.txt +0 -1570
- package/.code/agents/8/exec-call_UtrjAcLbhYLatxR4O97fZgnm.txt +0 -2590
- package/.code/agents/82490bc9-f34e-4b1b-8a8e-bccc2e6254f5/error.txt +0 -3
- package/.code/agents/841/exec-call_7nTNhSBCNjTDUIJv7py6CepO.txt +0 -3299
- package/.code/agents/841/exec-call_TLI0yUdUijuUAvI4o3DXEvHO.txt +0 -3299
- package/.code/agents/9/exec-call_XaABQT1hIlRpnKZ2uyBMWsTC.txt +0 -1882
- package/.code/agents/941/exec-call_GuGHRx7NNXWIDAnxUG2NEWPa.txt +0 -2594
- package/.code/agents/95d9fbab-19a2-48af-83f9-c792566a347f/error.txt +0 -1
- package/.code/agents/b0098cb8-cb32-4ada-9bc4-37c587518896/result.txt +0 -170
- package/.code/agents/b4fe59a4-81df-42e2-a112-0153e504faca/error.txt +0 -1
- package/.code/agents/bf4ce152-f623-49d7-aa52-c18631625c3c/error.txt +0 -3
- package/.code/agents/d7d1db75-d7eb-468e-adea-4ef4d916d187/status.txt +0 -1
- package/.code/agents/e2baa9c8-bac3-49e3-a39d-024333e6a990/status.txt +0 -1
- package/.code/agents/e350b8c3-8483-408c-b2bb-94515f492a11/error.txt +0 -3
- package/.code/agents/e63f9919-719f-4ad0-bccf-01b1a596e1e9/status.txt +0 -1
- package/.code/agents/e71695a8-3044-478d-8f12-ed13d02884c7/status.txt +0 -1
- package/.code/agents/f95b7464-3e25-4897-b153-c8dfd63fd605/error.txt +0 -5
- package/.code/agents/fa3c5ddf-cdf7-47a2-930a-b806c6363689/status.txt +0 -1
- package/.github/workflows/pr-description-check.yml +0 -88
- package/AGENTS.md +0 -36
- package/NUL +0 -1
- package/docs/README.md +0 -72
- package/docs/getting-started/CONFIGURATION.md +0 -175
- package/docs/getting-started/INSTALLATION.md +0 -333
- package/docs/getting-started/QUICKSTART.md +0 -282
- package/docs/guides/ARCHITECTURE.md +0 -533
- package/docs/guides/DEPLOYMENT.md +0 -189
- package/docs/guides/INTEGRATION_TESTING.md +0 -730
- package/docs/guides/TESTING.md +0 -591
- package/docs/reconciliation-flow.md +0 -83
- package/docs/reference/EXAMPLES.md +0 -946
- package/docs/reference/TOOLS.md +0 -348
- package/docs/reference/TROUBLESHOOTING.md +0 -481
- package/package.json.tmp +0 -105
- package/temp-recon.ts +0 -126
- package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_09-04-53.json +0 -23
- package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_10-37-42.json +0 -23
- package/test-exports/ynab_account_e9ddc2a6_minimal_4items_2025-11-19_09-02-09.json +0 -44
- package/test-exports/ynab_account_e9ddc2a6_minimal_6items_2025-11-19_10-37-52.json +0 -58
- package/test-exports/ynab_since_2025-10-16_account_53298e13_238items_2025-11-28_13-46-20.json +0 -3662
- package/test-exports/ynab_since_2025-11-01_account_4c18e9f0_minimal_14items_2025-11-16_10-07-10.json +0 -115
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Failed to execute code-gpt-5.1-codex-mini: program not found
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
I'm using the writing-plans skill to create the implementation plan.
|
|
2
|
-
|
|
3
|
-
# MCP Resilience Implementation Plan
|
|
4
|
-
|
|
5
|
-
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
6
|
-
|
|
7
|
-
**Goal:** Harden the MCP server by validating every tool’s metadata schema and making `clear_cache` fully reset delta/caching state so knowledge doesn’t drift while keeping diagnostics accurate.
|
|
8
|
-
|
|
9
|
-
**Architecture:** Validate metadata against generated `zod` schemas inside `ToolRegistry`, expose mismatches immediately, and delegate cache clearing to `DeltaCache.forceFullRefresh()` so both the LRU cache and `ServerKnowledgeStore` reset before diagnostics observe the new state.
|
|
10
|
-
|
|
11
|
-
**Tech Stack:** TypeScript 5/Node 18+, `zod`/`zod-validation-error`, MCP SDK server wiring in `src/server`, Vitest for fast unit/integration suites, and Markdown docs in `docs/reference/TOOLS.md`.
|
|
12
|
-
|
|
13
|
-
### Task 1: Tighten tool metadata schema validation
|
|
14
|
-
|
|
15
|
-
**Files:**
|
|
16
|
-
- Modify: `src/server/toolRegistry.ts`
|
|
17
|
-
- Modify: `src/server/__tests__/toolRegistry.test.ts`
|
|
18
|
-
|
|
19
|
-
**Step 1: Write the failing test**
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
it('rejects registration when metadata inputJsonSchema diverges from the handler schema', () => {
|
|
23
|
-
const registry = new ToolRegistry({
|
|
24
|
-
withSecurityWrapper: vi.fn().mockReturnValue(() => async (handler) => handler({})),
|
|
25
|
-
errorHandler: mockedErrorHandler,
|
|
26
|
-
responseFormatter: responseFormatter,
|
|
27
|
-
});
|
|
28
|
-
const mismatchedMetadata = { type: 'object', properties: { bogus: { type: 'string' } } };
|
|
29
|
-
expect(() =>
|
|
30
|
-
registry.register({
|
|
31
|
-
name: 'budget-sync',
|
|
32
|
-
description: 'Sync budget data',
|
|
33
|
-
inputSchema: z.object({ budget_id: z.string().min(1) }).strict(),
|
|
34
|
-
handler: async () => ({ content: [{ type: 'text', text: responseFormatter.format({}) }] }),
|
|
35
|
-
metadata: { inputJsonSchema: mismatchedMetadata },
|
|
36
|
-
}),
|
|
37
|
-
).toThrow('metadata input schema must match generated schema for tool "budget-sync"');
|
|
38
|
-
});
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**Step 2: Run the test to verify it fails**
|
|
42
|
-
|
|
43
|
-
Run: `npm run test:unit -- --runInBand src/server/__tests__/toolRegistry.test.ts --testNamePattern "metadata input schema"`
|
|
44
|
-
Expected: FAIL because the registry currently accepts mismatched metadata.
|
|
45
|
-
|
|
46
|
-
**Step 3: Implement the minimal enforcement**
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
private ensureMetadataSchemaMatches(definition: ToolDefinition): void {
|
|
50
|
-
const generatedSchema = this.generateJsonSchema(definition.inputSchema, 'input');
|
|
51
|
-
if (definition.metadata?.inputJsonSchema) {
|
|
52
|
-
if (JSON.stringify(generatedSchema) !== JSON.stringify(definition.metadata.inputJsonSchema)) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`metadata input schema must match generated schema for tool "${definition.name}"`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
definition.metadata = {
|
|
59
|
-
...definition.metadata,
|
|
60
|
-
inputJsonSchema: generatedSchema,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Call `this.ensureMetadataSchemaMatches(definition);` near the top of `register` before storing the tool so `metadata.inputJsonSchema` is always populated (and validated) for `listTools()`. This also means `ToolRegistry.listTools()` no longer needs to fall back to `generateJsonSchema` when metadata is present.
|
|
67
|
-
|
|
68
|
-
**Step 4: Run the test to confirm it now passes**
|
|
69
|
-
|
|
70
|
-
Run: `npm run test:unit -- --runInBand src/server/__tests__/toolRegistry.test.ts --testNamePattern "metadata input schema"`
|
|
71
|
-
Expected: PASS.
|
|
72
|
-
|
|
73
|
-
**Step 5: Commit**
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
git add src/server/toolRegistry.ts src/server/__tests__/toolRegistry.test.ts
|
|
77
|
-
git commit -m "fix: validate tool metadata schemas at registration"
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Task 2: Reset delta knowledge when clearing the cache
|
|
81
|
-
|
|
82
|
-
**Files:**
|
|
83
|
-
- Modify: `src/server/YNABMCPServer.ts`
|
|
84
|
-
- Modify: `src/server/__tests__/YNABMCPServer.integration.test.ts`
|
|
85
|
-
- Modify: `docs/reference/TOOLS.md`
|
|
86
|
-
|
|
87
|
-
**Step 1: Write the failing integration test**
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
it(
|
|
91
|
-
'resets delta knowledge entries when clear_cache runs',
|
|
92
|
-
{ meta: { tier: 'domain', domain: 'server' } },
|
|
93
|
-
async (ctx) => {
|
|
94
|
-
await skipOnRateLimit(async () => {
|
|
95
|
-
const token = accessToken();
|
|
96
|
-
await registry.executeTool({
|
|
97
|
-
name: 'list_accounts',
|
|
98
|
-
accessToken: token,
|
|
99
|
-
arguments: { budget_id: budgetsResult?.budgets?.[0]?.id },
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const before = await registry.executeTool({
|
|
103
|
-
name: 'diagnostic_info',
|
|
104
|
-
accessToken: token,
|
|
105
|
-
arguments: { include_delta: true },
|
|
106
|
-
});
|
|
107
|
-
const beforeData = JSON.parse(before.content?.[0]?.text ?? '{}');
|
|
108
|
-
expect(beforeData.delta?.knowledge_entries).toBeGreaterThan(0);
|
|
109
|
-
|
|
110
|
-
await registry.executeTool({ name: 'clear_cache', accessToken: token, arguments: {} });
|
|
111
|
-
|
|
112
|
-
const after = await registry.executeTool({
|
|
113
|
-
name: 'diagnostic_info',
|
|
114
|
-
accessToken: token,
|
|
115
|
-
arguments: { include_delta: true },
|
|
116
|
-
});
|
|
117
|
-
const afterData = JSON.parse(after.content?.[0]?.text ?? '{}');
|
|
118
|
-
expect(afterData.delta?.knowledge_entries).toBe(0);
|
|
119
|
-
}, ctx);
|
|
120
|
-
},
|
|
121
|
-
);
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Step 2: Run the integration test to verify it fails**
|
|
125
|
-
|
|
126
|
-
Run: `npm run test:integration:domain -- --testNamePattern "clear cache runs"`
|
|
127
|
-
Expected: FAIL because `clear_cache` currently only clears `cacheManager`, leaving `ServerKnowledgeStore` populated.
|
|
128
|
-
|
|
129
|
-
**Step 3: Implement the minimal fix**
|
|
130
|
-
|
|
131
|
-
- Update the `clear_cache` handler in `setupToolRegistry` to call `this.deltaCache.forceFullRefresh()` instead of directly `cacheManager.clear()`, ensuring both the cache and knowledge store reset:
|
|
132
|
-
|
|
133
|
-
```ts
|
|
134
|
-
handler: async () => {
|
|
135
|
-
this.deltaCache.forceFullRefresh();
|
|
136
|
-
return {
|
|
137
|
-
content: [{ type: 'text', text: responseFormatter.format({ success: true }) }],
|
|
138
|
-
};
|
|
139
|
-
},
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
- Update `docs/reference/TOOLS.md` entry to explain the stronger guarantee:
|
|
143
|
-
|
|
144
|
-
```md
|
|
145
|
-
| `clear_cache` | Clear the cache and reset delta knowledge so clients can start fresh | None |
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**Step 4: Run the integration test to confirm it passes**
|
|
149
|
-
|
|
150
|
-
Run: `npm run test:integration:domain -- --testNamePattern "clear cache runs"`
|
|
151
|
-
Expected: PASS.
|
|
152
|
-
|
|
153
|
-
**Step 5: Commit**
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
git add src/server/YNABMCPServer.ts src/server/__tests__/YNABMCPServer.integration.test.ts docs/reference/TOOLS.md
|
|
157
|
-
git commit -m "feat: reset delta knowledge when cache is cleared"
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
Because the sandbox is read-only, I couldn’t save this plan to `docs/plans/2025-11-21-mcp-resilience.md`; please copy the above Markdown there in a workspace-write session before executing the tasks.
|
|
163
|
-
|
|
164
|
-
- **Plan scope:** Adds schema validation in `src/server/toolRegistry.ts` plus a new regression test in `src/server/__tests__/toolRegistry.test.ts`, and modifies `clear_cache` in `src/server/YNABMCPServer.ts` with an integration test addition and doc update in `docs/reference/TOOLS.md`.
|
|
165
|
-
- **Testing:** Run the targeted unit test via `npm run test:unit -- --runInBand src/server/__tests__/toolRegistry.test.ts --testNamePattern "metadata input schema"` and the integration slice via `npm run test:integration:domain -- --testNamePattern "clear cache runs"` after making the code changes.
|
|
166
|
-
|
|
167
|
-
Next steps:
|
|
168
|
-
1. Execute the described plan in a writable worktree (create `docs/plans/2025-11-21-mcp-resilience.md` with the above content first) and implement Task 1’s schema validation.
|
|
169
|
-
2. Run the targeted unit test from Task 1 to confirm failure, then fix the code, rerun to confirm success.
|
|
170
|
-
3. Implement Task 2, add the integration test, update `clear_cache`, refresh `docs/reference/TOOLS.md`, and run `npm run test:integration:domain -- --testNamePattern "clear cache runs"`.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Required agent 'gemini' is not installed or not in PATH
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
Command failed: Error loading configuration: config profile `Smoke test: from the current repo, run `pwd` and `git status -sb`, then list top-level files/directories and print a short summary. No file writes or edits.
|
|
2
|
-
|
|
3
|
-
[Running in read-only mode - no modifications allowed]` not found
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Agent cancelled
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Agent cancelled
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
Command failed: Error loading configuration: config profile `You are helping craft an implementation plan for the YNAB MCP Server repo (Model Context Protocol server for YNAB). Repo root at C:/Users/ksutk/projects/ynab-mcpb. Key info: TypeScript/Node 18+, ts source in src/, server wiring in src/server, tools in src/tools, utils in src/utils, entry at src/index.ts. Build: npm run build (lint+tsc+bundle) outputs dist/. Tests use Vitest with projects (unit, integration, e2e). package.json scripts include build:prod, lint:fix, test:unit, test:integration, test:e2e, package:mcpb. Docs in docs/. Current version 0.13.4. Goal: propose a concrete step-by-step implementation plan for the next iteration to improve the project. Include where to change code (paths), suggested tests to add/run, and rationale. Assume current tests passing (test-results show success). Focus on actionable tasks (2-5 min steps) using TDD mindset. Deliver plan structure we can hand to engineer. Do not assume write access.
|
|
2
|
-
|
|
3
|
-
[Running in read-only mode - no modifications allowed]` not found
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Agent cancelled
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Agent cancelled
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
Command failed: Error loading configuration: config profile `Context: cwd: C:\Users\ksutk\projects\ynab-mcpb. This is only to verify whether a gemini-3-pro backed agent can successfully start and complete.
|
|
2
|
-
|
|
3
|
-
Agent: Minimal Gemini smoke test: from the ynab-mcpb repo, run `git status -sb` and list top-level directories, then print a short summary and exit. No file writes required.
|
|
4
|
-
|
|
5
|
-
[Running in read-only mode - no modifications allowed]` not found
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Agent cancelled
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
name: PR Description Check
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [opened, edited, synchronize]
|
|
6
|
-
|
|
7
|
-
permissions:
|
|
8
|
-
contents: read
|
|
9
|
-
issues: write
|
|
10
|
-
pull-requests: read
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
check-description:
|
|
14
|
-
runs-on: ubuntu-latest
|
|
15
|
-
steps:
|
|
16
|
-
- name: Check PR Description Format
|
|
17
|
-
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
18
|
-
with:
|
|
19
|
-
script: |
|
|
20
|
-
const body = context.payload.pull_request.body || '';
|
|
21
|
-
|
|
22
|
-
// Required sections from template
|
|
23
|
-
const requiredSections = [
|
|
24
|
-
'Type of change',
|
|
25
|
-
'Public API surface checklist',
|
|
26
|
-
'Versioning and release'
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const missingSections = requiredSections.filter(section =>
|
|
30
|
-
!body.includes(section)
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
if (missingSections.length > 0) {
|
|
34
|
-
// Build comment as array to avoid YAML indentation issues
|
|
35
|
-
const commentLines = [
|
|
36
|
-
'⚠️ **PR Description Check Failed**',
|
|
37
|
-
'',
|
|
38
|
-
'The PR description is missing required sections from the template:',
|
|
39
|
-
...missingSections.map(s => `- ${s}`),
|
|
40
|
-
'',
|
|
41
|
-
'Please update the description to include these sections. You can view the template at:',
|
|
42
|
-
`https://github.com/${context.repo.owner}/${context.repo.repo}/blob/master/.github/pull_request_template.md`,
|
|
43
|
-
'',
|
|
44
|
-
'Or run this command to update it:',
|
|
45
|
-
'```bash',
|
|
46
|
-
`gh pr edit ${context.payload.pull_request.number} --body-file .github/pull_request_template.md`,
|
|
47
|
-
'```'
|
|
48
|
-
];
|
|
49
|
-
const comment = commentLines.join('\n');
|
|
50
|
-
|
|
51
|
-
// Upsert comment: update existing bot comment or create new one
|
|
52
|
-
const botCommentPrefix = '⚠️ **PR Description Check Failed**';
|
|
53
|
-
// Paginate through all comments to handle PRs with >30 comments
|
|
54
|
-
const comments = await github.paginate(
|
|
55
|
-
github.rest.issues.listComments,
|
|
56
|
-
{
|
|
57
|
-
owner: context.repo.owner,
|
|
58
|
-
repo: context.repo.repo,
|
|
59
|
-
issue_number: context.payload.pull_request.number,
|
|
60
|
-
per_page: 100
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const existingComment = comments.find(
|
|
65
|
-
c => c.user.type === 'Bot' && c.body.startsWith(botCommentPrefix)
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
if (existingComment) {
|
|
69
|
-
await github.rest.issues.updateComment({
|
|
70
|
-
owner: context.repo.owner,
|
|
71
|
-
repo: context.repo.repo,
|
|
72
|
-
comment_id: existingComment.id,
|
|
73
|
-
body: comment
|
|
74
|
-
});
|
|
75
|
-
} else {
|
|
76
|
-
await github.rest.issues.createComment({
|
|
77
|
-
owner: context.repo.owner,
|
|
78
|
-
repo: context.repo.repo,
|
|
79
|
-
issue_number: context.payload.pull_request.number,
|
|
80
|
-
body: comment
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Fail the check
|
|
85
|
-
core.setFailed(`Missing required sections: ${missingSections.join(', ')}`);
|
|
86
|
-
} else {
|
|
87
|
-
console.log('✅ All required sections present in PR description');
|
|
88
|
-
}
|
package/AGENTS.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Repository Guidelines
|
|
2
|
-
|
|
3
|
-
## Project Structure & Module Organization
|
|
4
|
-
|
|
5
|
-
`src/` hosts all TypeScript modules: `server/` wires the MCP host, `tools/` defines tool handlers, `utils/` shares primitives, and `index.ts` is the entry point.
|
|
6
|
-
Tests live in `src/__tests__` (unit, integration, e2e, performance) with sanitized fixtures in `test-exports/` and artifacts in `test-results/`.
|
|
7
|
-
Documentation stays in `docs/`, automation in `scripts/`, and compiled output in `dist/` plus `dist/bundle/`; never edit generated files directly.
|
|
8
|
-
|
|
9
|
-
## Build, Test, and Development Commands
|
|
10
|
-
|
|
11
|
-
- `npm run dev` - incremental TypeScript build while coding.
|
|
12
|
-
- `npm run build` - clean `dist/`, compile, then esbuild-bundle.
|
|
13
|
-
- `npm run build:prod` / `npm run package:mcpb` - production bundle with verification and MCPB packing.
|
|
14
|
-
- `npm start` or `npm run start:mcp` - launch compiled server with `.env`.
|
|
15
|
-
- `npm run validate-env` - confirm required secrets before tool runs.
|
|
16
|
-
|
|
17
|
-
## Coding Style & Naming Conventions
|
|
18
|
-
|
|
19
|
-
Prettier enforces 2-space indent, 100-char width, single quotes, and semicolons; verify with `npm run format:check`.
|
|
20
|
-
ESLint (`npm run lint`) must pass before commits; prefer `npm run lint:fix` for safe rewrites.
|
|
21
|
-
Name files after their capability (`budgetService.ts`, `create-account.tool.ts`) and keep MCP tool identifiers kebab-case with ES modules and explicit dependency injection.
|
|
22
|
-
|
|
23
|
-
## Testing Guidelines
|
|
24
|
-
|
|
25
|
-
Vitest powers the suite: `npm test` runs everything then filters failures into `test-results.json`, while `test:unit`, `test:integration`, `test:e2e`, `test:performance`, and `test:coverage` target specific goals.
|
|
26
|
-
Use `test:comprehensive` (tsx runner) for orchestration flows, mirror test filenames to the feature, and update fixtures only with scrubbed data.
|
|
27
|
-
|
|
28
|
-
## Commit & Pull Request Guidelines
|
|
29
|
-
|
|
30
|
-
History follows Conventional Commits (`docs:`, `fix:`, `refactor:`); keep patches focused and note verification commands in every PR.
|
|
31
|
-
Run `npm run pr:description` to refresh `.pr-description.md` before `gh pr create`, link issues, and attach screenshots or sample JSON for user-facing changes.
|
|
32
|
-
|
|
33
|
-
## Environment & Security Tips
|
|
34
|
-
|
|
35
|
-
Clone `.env` from `.env.example`, set `YNAB_ACCESS_TOKEN` plus cache settings, then rerun `npm run validate-env` after edits.
|
|
36
|
-
Avoid logging secrets, prefer sample budgets when demonstrating behaviors, and delete stray exports from `test-exports/` before pushing.
|
package/NUL
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dir: cannot access '/B': No such file or directory
|
package/docs/README.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# YNAB MCP Server Documentation
|
|
2
|
-
|
|
3
|
-
Complete documentation for the YNAB Model Context Protocol Server.
|
|
4
|
-
|
|
5
|
-
## 📚 Documentation Overview
|
|
6
|
-
|
|
7
|
-
### Getting Started
|
|
8
|
-
New to the YNAB MCP Server? Start here:
|
|
9
|
-
|
|
10
|
-
- **[Quick Start](getting-started/QUICKSTART.md)** - Fast path to testing with Claude Desktop
|
|
11
|
-
- **[Installation](getting-started/INSTALLATION.md)** - Detailed installation instructions
|
|
12
|
-
- **[Configuration](getting-started/CONFIGURATION.md)** - Environment variables and settings
|
|
13
|
-
|
|
14
|
-
### Guides
|
|
15
|
-
Learn how to develop with and extend the server:
|
|
16
|
-
|
|
17
|
-
- **[Architecture](guides/ARCHITECTURE.md)** - Server architecture and core components
|
|
18
|
-
- **[Testing](guides/TESTING.md)** - Automated and manual testing strategies
|
|
19
|
-
- **[Deployment](guides/DEPLOYMENT.md)** - Production deployment instructions
|
|
20
|
-
|
|
21
|
-
### Reference
|
|
22
|
-
Complete API and technical reference:
|
|
23
|
-
|
|
24
|
-
- **[API Reference](reference/API.md)** - Complete tool documentation with examples
|
|
25
|
-
- **[Tools Quick Reference](reference/TOOLS.md)** - Quick tool catalog and parameter guide
|
|
26
|
-
- **[Examples](reference/EXAMPLES.md)** - Practical usage examples and workflows
|
|
27
|
-
- **[Troubleshooting](reference/TROUBLESHOOTING.md)** - Common issues, solutions, and debugging
|
|
28
|
-
|
|
29
|
-
## 🎯 Quick Navigation by Task
|
|
30
|
-
|
|
31
|
-
### I want to...
|
|
32
|
-
|
|
33
|
-
**Get Started**
|
|
34
|
-
- Install and configure → [Installation](getting-started/INSTALLATION.md)
|
|
35
|
-
- Test quickly → [Quick Start](getting-started/QUICKSTART.md)
|
|
36
|
-
- Understand the architecture → [Architecture](guides/ARCHITECTURE.md)
|
|
37
|
-
|
|
38
|
-
**Develop**
|
|
39
|
-
- Create a new tool → [Architecture Guide](guides/ARCHITECTURE.md#developing-tools-with-v08x)
|
|
40
|
-
- Understand the architecture → [Architecture](guides/ARCHITECTURE.md)
|
|
41
|
-
|
|
42
|
-
**Troubleshoot**
|
|
43
|
-
- Common issues → [Troubleshooting](reference/TROUBLESHOOTING.md)
|
|
44
|
-
|
|
45
|
-
**Test**
|
|
46
|
-
- Run automated tests → [Testing Guide](guides/TESTING.md)
|
|
47
|
-
|
|
48
|
-
**Deploy**
|
|
49
|
-
- Deploy to production → [Deployment Guide](guides/DEPLOYMENT.md)
|
|
50
|
-
- Configure for Claude Desktop → [Quick Start](getting-started/QUICKSTART.md#claude-desktop-integration)
|
|
51
|
-
|
|
52
|
-
## 🔗 External Resources
|
|
53
|
-
|
|
54
|
-
- **[YNAB API Documentation](https://api.youneedabudget.com/)** - Official YNAB API docs
|
|
55
|
-
- **[Model Context Protocol](https://modelcontextprotocol.io/)** - MCP specification
|
|
56
|
-
- **[Project Repository](https://github.com/dizzlkheinz/mcp-for-ynab)** - GitHub repository
|
|
57
|
-
- **[Release Notes](https://github.com/dizzlkheinz/mcp-for-ynab/releases)** - Version history and changelog
|
|
58
|
-
|
|
59
|
-
## 💡 Need Help?
|
|
60
|
-
|
|
61
|
-
- **Documentation Issue?** Check the [Troubleshooting Guide](reference/TROUBLESHOOTING.md)
|
|
62
|
-
- **Bug Report?** [Open an issue](https://github.com/dizzlkheinz/mcp-for-ynab/issues/new?template=bug_report.md)
|
|
63
|
-
- **Feature Request?** [Request a feature](https://github.com/dizzlkheinz/mcp-for-ynab/issues/new?template=feature_request.md)
|
|
64
|
-
- **Question?** Check existing [GitHub Discussions](https://github.com/dizzlkheinz/mcp-for-ynab/discussions)
|
|
65
|
-
|
|
66
|
-
## 📄 License
|
|
67
|
-
|
|
68
|
-
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the [LICENSE](../LICENSE) file for details.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
**Quick Links**: [Main README](../README.md) | [API Reference](reference/API.md) | [Quick Start](getting-started/QUICKSTART.md) | [Architecture](guides/ARCHITECTURE.md)
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# Environment Configuration Guide
|
|
2
|
-
|
|
3
|
-
This document provides detailed information about environment variables and configuration options for the YNAB MCP Server.
|
|
4
|
-
|
|
5
|
-
## Environment Variables
|
|
6
|
-
|
|
7
|
-
### Required Variables
|
|
8
|
-
|
|
9
|
-
#### YNAB_ACCESS_TOKEN
|
|
10
|
-
|
|
11
|
-
- **Type**: String
|
|
12
|
-
- **Required**: Yes
|
|
13
|
-
- **Description**: Your YNAB Personal Access Token for API authentication
|
|
14
|
-
- **Security**: Highly sensitive - never commit to version control
|
|
15
|
-
- **Format**: Alphanumeric string (typically 64 characters)
|
|
16
|
-
- **Example**: `YNAB_ACCESS_TOKEN=1234567890abcdef...`
|
|
17
|
-
|
|
18
|
-
**How to obtain**:
|
|
19
|
-
1. Log in to [YNAB Web App](https://app.youneedabudget.com)
|
|
20
|
-
2. Go to Account Settings → Developer Settings
|
|
21
|
-
3. Click "New Token"
|
|
22
|
-
4. Provide a descriptive name
|
|
23
|
-
5. Copy the token immediately (it's only shown once)
|
|
24
|
-
|
|
25
|
-
### Optional Variables
|
|
26
|
-
|
|
27
|
-
#### YNAB_DEFAULT_BUDGET_ID
|
|
28
|
-
|
|
29
|
-
- **Type**: String
|
|
30
|
-
- **Required**: No
|
|
31
|
-
- **Description**: Sets the default budget ID to use for all operations if not explicitly provided.
|
|
32
|
-
- **Example**: `YNAB_DEFAULT_BUDGET_ID=12345678-1234-1234-1234-123456789012`
|
|
33
|
-
|
|
34
|
-
#### NODE_ENV
|
|
35
|
-
|
|
36
|
-
- **Type**: String
|
|
37
|
-
- **Required**: No
|
|
38
|
-
- **Default**: `development`
|
|
39
|
-
- **Valid Values**: `development`, `production`, `test`
|
|
40
|
-
- **Description**: Specifies the runtime environment
|
|
41
|
-
- **Example**: `NODE_ENV=production`
|
|
42
|
-
|
|
43
|
-
#### LOG_LEVEL
|
|
44
|
-
|
|
45
|
-
- **Type**: String
|
|
46
|
-
- **Required**: No
|
|
47
|
-
- **Default**: `info`
|
|
48
|
-
- **Valid Values**: `error`, `warn`, `info`, `debug`
|
|
49
|
-
- **Description**: Controls the verbosity of application logging
|
|
50
|
-
- **Example**: `LOG_LEVEL=warn`
|
|
51
|
-
|
|
52
|
-
#### YNAB_MCP_MINIFY_OUTPUT
|
|
53
|
-
|
|
54
|
-
- **Type**: Boolean
|
|
55
|
-
- **Required**: No
|
|
56
|
-
- **Default**: `true`
|
|
57
|
-
- **Valid Values**: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off`
|
|
58
|
-
- **Description**: Controls whether tool responses are returned as minified JSON to save context.
|
|
59
|
-
- **Example**: `YNAB_MCP_MINIFY_OUTPUT=true`
|
|
60
|
-
|
|
61
|
-
#### YNAB_MCP_PRETTY_SPACES
|
|
62
|
-
|
|
63
|
-
- **Type**: Number
|
|
64
|
-
- **Required**: No
|
|
65
|
-
- **Default**: `2`
|
|
66
|
-
- **Description**: Number of spaces to use when pretty-printing JSON. Only used when `YNAB_MCP_MINIFY_OUTPUT=false`.
|
|
67
|
-
- **Example**: `YNAB_MCP_PRETTY_SPACES=2`
|
|
68
|
-
|
|
69
|
-
## Configuration Files
|
|
70
|
-
|
|
71
|
-
### .env File
|
|
72
|
-
|
|
73
|
-
Create a `.env` file in your project root for local development:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
# YNAB Configuration
|
|
77
|
-
YNAB_ACCESS_TOKEN=your_personal_access_token_here
|
|
78
|
-
|
|
79
|
-
# Application Configuration
|
|
80
|
-
NODE_ENV=development
|
|
81
|
-
LOG_LEVEL=info
|
|
82
|
-
|
|
83
|
-
# Output formatting
|
|
84
|
-
# Minify JSON output (saves context)
|
|
85
|
-
YNAB_MCP_MINIFY_OUTPUT=true
|
|
86
|
-
# Pretty spaces when not minifying
|
|
87
|
-
YNAB_MCP_PRETTY_SPACES=2
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Important**:
|
|
91
|
-
- Add `.env` to your `.gitignore` file
|
|
92
|
-
- Never commit `.env` files to version control
|
|
93
|
-
- Use different `.env` files for different environments
|
|
94
|
-
|
|
95
|
-
## Environment Validation
|
|
96
|
-
|
|
97
|
-
The server includes built-in environment validation that runs automatically during startup:
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
# Validate current environment
|
|
101
|
-
npm run validate-env
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Validation Rules
|
|
105
|
-
|
|
106
|
-
The validation script checks:
|
|
107
|
-
|
|
108
|
-
1. **Required Variables**:
|
|
109
|
-
- Presence of `YNAB_ACCESS_TOKEN`
|
|
110
|
-
- Token format and minimum length
|
|
111
|
-
|
|
112
|
-
2. **Optional Variables**:
|
|
113
|
-
- Valid values for `NODE_ENV`
|
|
114
|
-
- Valid values for `LOG_LEVEL`
|
|
115
|
-
|
|
116
|
-
3. **Security Checks**:
|
|
117
|
-
- Warns if using development tokens in production
|
|
118
|
-
- Validates environment consistency
|
|
119
|
-
|
|
120
|
-
## Platform-Specific Setup
|
|
121
|
-
|
|
122
|
-
### Windows (PowerShell)
|
|
123
|
-
|
|
124
|
-
```powershell
|
|
125
|
-
$env:YNAB_ACCESS_TOKEN="your_token_here"
|
|
126
|
-
$env:NODE_ENV="production"
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Linux/macOS
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
export YNAB_ACCESS_TOKEN="your_token_here"
|
|
133
|
-
export NODE_ENV="production"
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Docker
|
|
137
|
-
|
|
138
|
-
```dockerfile
|
|
139
|
-
ENV NODE_ENV=production
|
|
140
|
-
ENV YNAB_ACCESS_TOKEN=your_token_here
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Security Best Practices
|
|
144
|
-
|
|
145
|
-
### Token Management
|
|
146
|
-
|
|
147
|
-
1. **Rotation Strategy**: Rotate tokens every 90 days
|
|
148
|
-
2. **Access Control**: Limit who can access production environment variables
|
|
149
|
-
3. **Monitoring**: Log authentication attempts without exposing tokens
|
|
150
|
-
|
|
151
|
-
### Environment Isolation
|
|
152
|
-
|
|
153
|
-
1. **Separate Tokens**: Use different YNAB tokens for each environment
|
|
154
|
-
2. **Network Isolation**: Deploy environments in separate networks
|
|
155
|
-
3. **Access Controls**: Limit who can access production environment variables
|
|
156
|
-
|
|
157
|
-
## Troubleshooting
|
|
158
|
-
|
|
159
|
-
### Common Issues
|
|
160
|
-
|
|
161
|
-
#### Token Not Found
|
|
162
|
-
**Error**: `YNAB_ACCESS_TOKEN is required`
|
|
163
|
-
**Solutions**:
|
|
164
|
-
- Verify the environment variable is set
|
|
165
|
-
- Check `.env` file exists and contains the token
|
|
166
|
-
- Ensure the token is not wrapped in quotes incorrectly
|
|
167
|
-
|
|
168
|
-
#### Invalid Token Format
|
|
169
|
-
**Error**: `YNAB_ACCESS_TOKEN appears to be too short`
|
|
170
|
-
**Solutions**:
|
|
171
|
-
- Verify you copied the complete token from YNAB
|
|
172
|
-
- Check for extra spaces or characters
|
|
173
|
-
- Generate a new token if the current one is corrupted
|
|
174
|
-
|
|
175
|
-
For more environment configuration details, see the [Deployment Guide](DEPLOYMENT.md).
|