copilot-money-mcp 1.3.0 → 1.4.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/README.md CHANGED
@@ -331,6 +331,39 @@ COPILOT_CACHE_TTL_MINUTES=0 copilot-money-mcp
331
331
 
332
332
  You can also manually refresh the cache using the `refresh_database` tool.
333
333
 
334
+ ### Decode Timeout
335
+
336
+ For large databases (500MB+), you may need to increase the decode timeout. The default is 90 seconds (90,000ms).
337
+
338
+ **Via environment variable:**
339
+ ```bash
340
+ DECODE_TIMEOUT_MS=600000 copilot-money-mcp
341
+ ```
342
+
343
+ **Via CLI flag:**
344
+ ```bash
345
+ copilot-money-mcp --timeout 600000
346
+ ```
347
+
348
+ **In Claude Desktop config** (with increased Node.js memory for 1GB+ databases):
349
+ ```json
350
+ {
351
+ "mcpServers": {
352
+ "copilot-money": {
353
+ "command": "node",
354
+ "args": [
355
+ "--max-old-space-size=4096",
356
+ "/path/to/copilot-money-mcp/dist/cli.js",
357
+ "--db-path",
358
+ "/path/to/your/database",
359
+ "--timeout",
360
+ "600000"
361
+ ]
362
+ }
363
+ }
364
+ }
365
+ ```
366
+
334
367
  ## Known Limitations
335
368
 
336
369
  ### Local Cache Size
@@ -359,6 +392,14 @@ If you see "Database not available":
359
392
  3. Verify `.ldb` files exist in the directory
360
393
  4. Provide custom path: `copilot-money-mcp --db-path /path/to/database`
361
394
 
395
+ ### Decode Worker Timed Out (Large Databases)
396
+
397
+ If you see "Decode worker timed out after Xms":
398
+ 1. Your database may be too large for the default 90-second timeout
399
+ 2. Increase the timeout: `copilot-money-mcp --timeout 300000` (5 minutes)
400
+ 3. For databases over 1GB, also increase Node.js memory: `node --max-old-space-size=4096 dist/cli.js --timeout 300000`
401
+ 4. Set via environment variable: `DECODE_TIMEOUT_MS=600000`
402
+
362
403
  ### No Transactions Found
363
404
 
364
405
  - Copilot Money may not have synced yet - open the app and wait for sync
package/dist/cli.js CHANGED
@@ -29527,7 +29527,17 @@ function processUserAccount(fields, docId, collection) {
29527
29527
  userAccountData.order = order;
29528
29528
  return userAccountData;
29529
29529
  }
29530
- function decodeAllCollectionsIsolated(dbPath, timeoutMs = 30000) {
29530
+ function getDecodeTimeoutMs() {
29531
+ const envValue = process.env.DECODE_TIMEOUT_MS;
29532
+ if (envValue !== undefined) {
29533
+ const ms = parseInt(envValue, 10);
29534
+ if (!isNaN(ms) && ms > 0) {
29535
+ return ms;
29536
+ }
29537
+ }
29538
+ return 90000;
29539
+ }
29540
+ function decodeAllCollectionsIsolated(dbPath, timeoutMs = getDecodeTimeoutMs()) {
29531
29541
  return new Promise((resolve, reject) => {
29532
29542
  const selfUrl = import.meta.url;
29533
29543
  const workerExt = selfUrl.endsWith(".ts") ? ".ts" : ".js";
@@ -30812,12 +30822,14 @@ class CopilotDatabase {
30812
30822
  _loadingAllCollections = null;
30813
30823
  _allCollectionsLoaded = false;
30814
30824
  _cacheLoadedAt = null;
30815
- constructor(dbPath) {
30825
+ decodeTimeoutMs;
30826
+ constructor(dbPath, decodeTimeoutMs) {
30816
30827
  if (dbPath) {
30817
30828
  this.dbPath = dbPath;
30818
30829
  } else {
30819
30830
  this.dbPath = findCopilotDatabase();
30820
30831
  }
30832
+ this.decodeTimeoutMs = decodeTimeoutMs;
30821
30833
  }
30822
30834
  requireDbPath() {
30823
30835
  if (!this.dbPath) {
@@ -30901,7 +30913,7 @@ class CopilotDatabase {
30901
30913
  await this._loadingAllCollections;
30902
30914
  return;
30903
30915
  }
30904
- this._loadingAllCollections = decodeAllCollectionsIsolated(this.requireDbPath());
30916
+ this._loadingAllCollections = decodeAllCollectionsIsolated(this.requireDbPath(), this.decodeTimeoutMs);
30905
30917
  try {
30906
30918
  const result = await this._loadingAllCollections;
30907
30919
  this._transactions = result.transactions;
@@ -32742,8 +32754,8 @@ class CopilotMoneyServer {
32742
32754
  db;
32743
32755
  tools;
32744
32756
  server;
32745
- constructor(dbPath) {
32746
- this.db = new CopilotDatabase(dbPath);
32757
+ constructor(dbPath, decodeTimeoutMs) {
32758
+ this.db = new CopilotDatabase(dbPath, decodeTimeoutMs);
32747
32759
  this.tools = new CopilotMoneyTools(this.db);
32748
32760
  this.server = new Server({
32749
32761
  name: "copilot-money-mcp",
@@ -32860,8 +32872,8 @@ class CopilotMoneyServer {
32860
32872
  });
32861
32873
  }
32862
32874
  }
32863
- async function runServer(dbPath) {
32864
- const server = new CopilotMoneyServer(dbPath);
32875
+ async function runServer(dbPath, decodeTimeoutMs) {
32876
+ const server = new CopilotMoneyServer(dbPath, decodeTimeoutMs);
32865
32877
  await server.run();
32866
32878
  }
32867
32879
 
@@ -32870,11 +32882,22 @@ function parseArgs() {
32870
32882
  const args = process.argv.slice(2);
32871
32883
  let dbPath;
32872
32884
  let verbose = false;
32885
+ let timeoutMs;
32873
32886
  for (let i = 0;i < args.length; i++) {
32874
32887
  const arg = args[i];
32875
32888
  if (arg === "--db-path" && i + 1 < args.length) {
32876
32889
  dbPath = args[i + 1];
32877
32890
  i++;
32891
+ } else if (arg === "--timeout" && i + 1 < args.length) {
32892
+ const rawValue = args[i + 1];
32893
+ const ms = parseInt(rawValue, 10);
32894
+ if (!isNaN(ms) && ms > 0) {
32895
+ timeoutMs = ms;
32896
+ } else {
32897
+ console.error(`Invalid --timeout value: ${rawValue} (must be a positive integer in milliseconds)`);
32898
+ process.exit(1);
32899
+ }
32900
+ i++;
32878
32901
  } else if (arg === "--verbose" || arg === "-v") {
32879
32902
  verbose = true;
32880
32903
  } else if (arg === "--help" || arg === "-h") {
@@ -32886,17 +32909,19 @@ Usage:
32886
32909
 
32887
32910
  Options:
32888
32911
  --db-path <path> Path to LevelDB database (default: Copilot Money's default location)
32912
+ --timeout <ms> Decode timeout in milliseconds (default: 90000 = 90 seconds)
32889
32913
  --verbose, -v Enable verbose logging
32890
32914
  --help, -h Show this help message
32891
32915
 
32892
32916
  Environment:
32917
+ DECODE_TIMEOUT_MS Override decode timeout (same as --timeout flag)
32893
32918
  The server uses stdio transport and logs to stderr.
32894
32919
  Claude Desktop will communicate with it via stdin/stdout.
32895
32920
  `);
32896
32921
  process.exit(0);
32897
32922
  }
32898
32923
  }
32899
- return { dbPath, verbose };
32924
+ return { dbPath, verbose, timeoutMs };
32900
32925
  }
32901
32926
  function configureLogging(verbose) {
32902
32927
  const originalError = console.error;
@@ -32912,7 +32937,7 @@ function configureLogging(verbose) {
32912
32937
  }
32913
32938
  }
32914
32939
  async function main() {
32915
- const { dbPath, verbose } = parseArgs();
32940
+ const { dbPath, verbose, timeoutMs } = parseArgs();
32916
32941
  configureLogging(verbose);
32917
32942
  try {
32918
32943
  if (verbose) {
@@ -32923,7 +32948,7 @@ async function main() {
32923
32948
  console.log("Using default Copilot Money database location");
32924
32949
  }
32925
32950
  }
32926
- await runServer(dbPath);
32951
+ await runServer(dbPath, timeoutMs);
32927
32952
  } catch (error48) {
32928
32953
  console.error("Server error:", error48);
32929
32954
  process.exit(1);
@@ -804,7 +804,7 @@ __export(exports_core2, {
804
804
  safeDecode: () => safeDecode,
805
805
  registry: () => registry,
806
806
  regexes: () => exports_regexes,
807
- process: () => process,
807
+ process: () => process2,
808
808
  prettifyError: () => prettifyError,
809
809
  parseAsync: () => parseAsync,
810
810
  parse: () => parse,
@@ -11268,7 +11268,7 @@ function initializeContext(params) {
11268
11268
  external: params?.external ?? undefined
11269
11269
  };
11270
11270
  }
11271
- function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
11271
+ function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
11272
11272
  var _a2;
11273
11273
  const def = schema._zod.def;
11274
11274
  const seen = ctx.seen.get(schema);
@@ -11305,7 +11305,7 @@ function process(schema, ctx, _params = { path: [], schemaPath: [] }) {
11305
11305
  if (parent) {
11306
11306
  if (!result.ref)
11307
11307
  result.ref = parent;
11308
- process(parent, ctx, params);
11308
+ process2(parent, ctx, params);
11309
11309
  ctx.seen.get(parent).isParent = true;
11310
11310
  }
11311
11311
  }
@@ -11581,14 +11581,14 @@ function isTransforming(_schema, _ctx) {
11581
11581
  }
11582
11582
  var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
11583
11583
  const ctx = initializeContext({ ...params, processors });
11584
- process(schema, ctx);
11584
+ process2(schema, ctx);
11585
11585
  extractDefs(ctx, schema);
11586
11586
  return finalize(ctx, schema);
11587
11587
  };
11588
11588
  var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
11589
11589
  const { libraryOptions, target } = params ?? {};
11590
11590
  const ctx = initializeContext({ ...libraryOptions ?? {}, target, io, processors });
11591
- process(schema, ctx);
11591
+ process2(schema, ctx);
11592
11592
  extractDefs(ctx, schema);
11593
11593
  return finalize(ctx, schema);
11594
11594
  };
@@ -11839,7 +11839,7 @@ var arrayProcessor = (schema, ctx, _json, params) => {
11839
11839
  if (typeof maximum === "number")
11840
11840
  json.maxItems = maximum;
11841
11841
  json.type = "array";
11842
- json.items = process(def.element, ctx, { ...params, path: [...params.path, "items"] });
11842
+ json.items = process2(def.element, ctx, { ...params, path: [...params.path, "items"] });
11843
11843
  };
11844
11844
  var objectProcessor = (schema, ctx, _json, params) => {
11845
11845
  const json = _json;
@@ -11848,7 +11848,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
11848
11848
  json.properties = {};
11849
11849
  const shape = def.shape;
11850
11850
  for (const key in shape) {
11851
- json.properties[key] = process(shape[key], ctx, {
11851
+ json.properties[key] = process2(shape[key], ctx, {
11852
11852
  ...params,
11853
11853
  path: [...params.path, "properties", key]
11854
11854
  });
@@ -11871,7 +11871,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
11871
11871
  if (ctx.io === "output")
11872
11872
  json.additionalProperties = false;
11873
11873
  } else if (def.catchall) {
11874
- json.additionalProperties = process(def.catchall, ctx, {
11874
+ json.additionalProperties = process2(def.catchall, ctx, {
11875
11875
  ...params,
11876
11876
  path: [...params.path, "additionalProperties"]
11877
11877
  });
@@ -11880,7 +11880,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
11880
11880
  var unionProcessor = (schema, ctx, json, params) => {
11881
11881
  const def = schema._zod.def;
11882
11882
  const isExclusive = def.inclusive === false;
11883
- const options = def.options.map((x, i) => process(x, ctx, {
11883
+ const options = def.options.map((x, i) => process2(x, ctx, {
11884
11884
  ...params,
11885
11885
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
11886
11886
  }));
@@ -11892,11 +11892,11 @@ var unionProcessor = (schema, ctx, json, params) => {
11892
11892
  };
11893
11893
  var intersectionProcessor = (schema, ctx, json, params) => {
11894
11894
  const def = schema._zod.def;
11895
- const a = process(def.left, ctx, {
11895
+ const a = process2(def.left, ctx, {
11896
11896
  ...params,
11897
11897
  path: [...params.path, "allOf", 0]
11898
11898
  });
11899
- const b = process(def.right, ctx, {
11899
+ const b = process2(def.right, ctx, {
11900
11900
  ...params,
11901
11901
  path: [...params.path, "allOf", 1]
11902
11902
  });
@@ -11913,11 +11913,11 @@ var tupleProcessor = (schema, ctx, _json, params) => {
11913
11913
  json.type = "array";
11914
11914
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
11915
11915
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
11916
- const prefixItems = def.items.map((x, i) => process(x, ctx, {
11916
+ const prefixItems = def.items.map((x, i) => process2(x, ctx, {
11917
11917
  ...params,
11918
11918
  path: [...params.path, prefixPath, i]
11919
11919
  }));
11920
- const rest = def.rest ? process(def.rest, ctx, {
11920
+ const rest = def.rest ? process2(def.rest, ctx, {
11921
11921
  ...params,
11922
11922
  path: [...params.path, restPath, ...ctx.target === "openapi-3.0" ? [def.items.length] : []]
11923
11923
  }) : null;
@@ -11957,7 +11957,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
11957
11957
  const keyBag = keyType._zod.bag;
11958
11958
  const patterns = keyBag?.patterns;
11959
11959
  if (def.mode === "loose" && patterns && patterns.size > 0) {
11960
- const valueSchema = process(def.valueType, ctx, {
11960
+ const valueSchema = process2(def.valueType, ctx, {
11961
11961
  ...params,
11962
11962
  path: [...params.path, "patternProperties", "*"]
11963
11963
  });
@@ -11967,12 +11967,12 @@ var recordProcessor = (schema, ctx, _json, params) => {
11967
11967
  }
11968
11968
  } else {
11969
11969
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
11970
- json.propertyNames = process(def.keyType, ctx, {
11970
+ json.propertyNames = process2(def.keyType, ctx, {
11971
11971
  ...params,
11972
11972
  path: [...params.path, "propertyNames"]
11973
11973
  });
11974
11974
  }
11975
- json.additionalProperties = process(def.valueType, ctx, {
11975
+ json.additionalProperties = process2(def.valueType, ctx, {
11976
11976
  ...params,
11977
11977
  path: [...params.path, "additionalProperties"]
11978
11978
  });
@@ -11987,7 +11987,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
11987
11987
  };
11988
11988
  var nullableProcessor = (schema, ctx, json, params) => {
11989
11989
  const def = schema._zod.def;
11990
- const inner = process(def.innerType, ctx, params);
11990
+ const inner = process2(def.innerType, ctx, params);
11991
11991
  const seen = ctx.seen.get(schema);
11992
11992
  if (ctx.target === "openapi-3.0") {
11993
11993
  seen.ref = def.innerType;
@@ -11998,20 +11998,20 @@ var nullableProcessor = (schema, ctx, json, params) => {
11998
11998
  };
11999
11999
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
12000
12000
  const def = schema._zod.def;
12001
- process(def.innerType, ctx, params);
12001
+ process2(def.innerType, ctx, params);
12002
12002
  const seen = ctx.seen.get(schema);
12003
12003
  seen.ref = def.innerType;
12004
12004
  };
12005
12005
  var defaultProcessor = (schema, ctx, json, params) => {
12006
12006
  const def = schema._zod.def;
12007
- process(def.innerType, ctx, params);
12007
+ process2(def.innerType, ctx, params);
12008
12008
  const seen = ctx.seen.get(schema);
12009
12009
  seen.ref = def.innerType;
12010
12010
  json.default = JSON.parse(JSON.stringify(def.defaultValue));
12011
12011
  };
12012
12012
  var prefaultProcessor = (schema, ctx, json, params) => {
12013
12013
  const def = schema._zod.def;
12014
- process(def.innerType, ctx, params);
12014
+ process2(def.innerType, ctx, params);
12015
12015
  const seen = ctx.seen.get(schema);
12016
12016
  seen.ref = def.innerType;
12017
12017
  if (ctx.io === "input")
@@ -12019,7 +12019,7 @@ var prefaultProcessor = (schema, ctx, json, params) => {
12019
12019
  };
12020
12020
  var catchProcessor = (schema, ctx, json, params) => {
12021
12021
  const def = schema._zod.def;
12022
- process(def.innerType, ctx, params);
12022
+ process2(def.innerType, ctx, params);
12023
12023
  const seen = ctx.seen.get(schema);
12024
12024
  seen.ref = def.innerType;
12025
12025
  let catchValue;
@@ -12033,32 +12033,32 @@ var catchProcessor = (schema, ctx, json, params) => {
12033
12033
  var pipeProcessor = (schema, ctx, _json, params) => {
12034
12034
  const def = schema._zod.def;
12035
12035
  const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
12036
- process(innerType, ctx, params);
12036
+ process2(innerType, ctx, params);
12037
12037
  const seen = ctx.seen.get(schema);
12038
12038
  seen.ref = innerType;
12039
12039
  };
12040
12040
  var readonlyProcessor = (schema, ctx, json, params) => {
12041
12041
  const def = schema._zod.def;
12042
- process(def.innerType, ctx, params);
12042
+ process2(def.innerType, ctx, params);
12043
12043
  const seen = ctx.seen.get(schema);
12044
12044
  seen.ref = def.innerType;
12045
12045
  json.readOnly = true;
12046
12046
  };
12047
12047
  var promiseProcessor = (schema, ctx, _json, params) => {
12048
12048
  const def = schema._zod.def;
12049
- process(def.innerType, ctx, params);
12049
+ process2(def.innerType, ctx, params);
12050
12050
  const seen = ctx.seen.get(schema);
12051
12051
  seen.ref = def.innerType;
12052
12052
  };
12053
12053
  var optionalProcessor = (schema, ctx, _json, params) => {
12054
12054
  const def = schema._zod.def;
12055
- process(def.innerType, ctx, params);
12055
+ process2(def.innerType, ctx, params);
12056
12056
  const seen = ctx.seen.get(schema);
12057
12057
  seen.ref = def.innerType;
12058
12058
  };
12059
12059
  var lazyProcessor = (schema, ctx, _json, params) => {
12060
12060
  const innerType = schema._zod.innerType;
12061
- process(innerType, ctx, params);
12061
+ process2(innerType, ctx, params);
12062
12062
  const seen = ctx.seen.get(schema);
12063
12063
  seen.ref = innerType;
12064
12064
  };
@@ -12110,7 +12110,7 @@ function toJSONSchema(input, params) {
12110
12110
  const defs = {};
12111
12111
  for (const entry of registry2._idmap.entries()) {
12112
12112
  const [_, schema] = entry;
12113
- process(schema, ctx2);
12113
+ process2(schema, ctx2);
12114
12114
  }
12115
12115
  const schemas = {};
12116
12116
  const external = {
@@ -12133,7 +12133,7 @@ function toJSONSchema(input, params) {
12133
12133
  return { schemas };
12134
12134
  }
12135
12135
  const ctx = initializeContext({ ...params, processors: allProcessors });
12136
- process(input, ctx);
12136
+ process2(input, ctx);
12137
12137
  extractDefs(ctx, input);
12138
12138
  return finalize(ctx, input);
12139
12139
  }
@@ -12179,7 +12179,7 @@ class JSONSchemaGenerator {
12179
12179
  });
12180
12180
  }
12181
12181
  process(schema, _params = { path: [], schemaPath: [] }) {
12182
- return process(schema, this.ctx, _params);
12182
+ return process2(schema, this.ctx, _params);
12183
12183
  }
12184
12184
  emit(schema, _params) {
12185
12185
  if (_params) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-money-mcp",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "MCP server for Copilot Money - AI-powered personal finance queries using local data",
5
5
  "keywords": [
6
6
  "mcp",