paisa-mcp 0.0.18 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -42482,7 +42482,7 @@ function registerBudgetTools(server, client) {
42482
42482
  year: exports_external.number()
42483
42483
  }
42484
42484
  }, async (body) => {
42485
- const data = await client.post("/api/budgets", body);
42485
+ const data = await client.put("/api/budgets", body);
42486
42486
  return { content: [{ type: "text", text: JSON.stringify(data) }] };
42487
42487
  });
42488
42488
  }
@@ -42900,9 +42900,9 @@ function registerInvestmentTools(server, client) {
42900
42900
  return { content: [{ type: "text", text: JSON.stringify(data) }] };
42901
42901
  });
42902
42902
  server.registerTool("upsert_investment", {
42903
- description: "Create or update an investment. " + "type=sip: omit id to add a new SIP (name, amount, startDate, sipDay, owner required); pass id to update an existing SIP, including pausing/stopping it via status. " + "type=fixed_deposit: create-only (bankName, amount, interestRate, startDate, maturityDate, owner required).",
42903
+ description: "Create or update an investment. " + "type=sip: omit id to add a new SIP (name, amount, startDate, sipDay, owner required); pass id to update an existing SIP, including pausing/stopping it via status. " + "type=fixed_deposit: create-only (bankName, amount, interestRate, startDate, maturityDate, owner required). " + "type=holding: create/update a manual stock/MF holding not pulled by a sync, e.g. a Groww position (name, holdingType, owner, investedAmount, currentValue required; re-upserting the same name+platform updates it).",
42904
42904
  inputSchema: {
42905
- type: exports_external.enum(["sip", "fixed_deposit"]).describe("Investment type"),
42905
+ type: exports_external.enum(["sip", "fixed_deposit", "holding"]).describe("Investment type"),
42906
42906
  id: exports_external.string().optional().describe("sip: SIP UUID — omit to add, pass to update"),
42907
42907
  name: exports_external.string().optional().describe('sip: fund name (e.g. "Parag Parikh Flexi Cap")'),
42908
42908
  startDate: exports_external.string().optional().describe("sip & fixed_deposit: YYYY-MM-DD"),
@@ -42915,10 +42915,43 @@ function registerInvestmentTools(server, client) {
42915
42915
  interestRate: exports_external.string().optional().describe("fixed_deposit: annual interest rate %"),
42916
42916
  maturityDate: exports_external.string().optional().describe("fixed_deposit: YYYY-MM-DD"),
42917
42917
  notes: exports_external.string().optional().describe("fixed_deposit: notes"),
42918
+ holdingType: exports_external.enum(["mutual_fund", "stock", "gold", "ppf", "nps", "other"]).optional().describe("holding: asset type"),
42919
+ platform: exports_external.string().optional().describe("holding: broker/platform (e.g. groww); defaults to 'manual'"),
42920
+ symbol: exports_external.string().optional().describe("holding: ticker symbol (optional)"),
42921
+ isin: exports_external.string().optional().describe("holding: ISIN (optional)"),
42922
+ units: exports_external.string().optional().describe("holding: units held (optional)"),
42923
+ investedAmount: exports_external.string().optional().describe("holding: total invested / cost"),
42924
+ currentValue: exports_external.string().optional().describe("holding: current market value"),
42918
42925
  amount: exports_external.string().optional().describe("sip: monthly SIP amount; fixed_deposit: principal amount"),
42919
- owner: exports_external.string().optional().describe("sip & fixed_deposit: owner")
42926
+ owner: exports_external.string().optional().describe("sip & fixed_deposit & holding: owner")
42920
42927
  }
42921
42928
  }, async ({ type, ...fields }) => {
42929
+ if (type === "holding") {
42930
+ const { name, holdingType, owner: owner2, platform, symbol, isin, units, investedAmount } = fields;
42931
+ const { currentValue } = fields;
42932
+ const missing2 = [
42933
+ ["name", name],
42934
+ ["holdingType", holdingType],
42935
+ ["owner", owner2],
42936
+ ["investedAmount", investedAmount],
42937
+ ["currentValue", currentValue]
42938
+ ].filter(([, v]) => v === undefined).map(([k]) => k);
42939
+ if (missing2.length > 0) {
42940
+ throw new Error(`Missing required fields for holding: ${missing2.join(", ")}`);
42941
+ }
42942
+ const data2 = await client.post("/api/investments/holdings", {
42943
+ name,
42944
+ holdingType,
42945
+ owner: owner2,
42946
+ platform: platform ?? "manual",
42947
+ symbol,
42948
+ isin,
42949
+ units,
42950
+ investedAmount,
42951
+ currentValue
42952
+ });
42953
+ return { content: [{ type: "text", text: JSON.stringify(data2) }] };
42954
+ }
42922
42955
  if (type === "sip") {
42923
42956
  const {
42924
42957
  id,
@@ -45735,6 +45768,16 @@ async function backfillPersons(client, crypto3, opts = {}) {
45735
45768
  function dedupeKey(date4, description, amount, type) {
45736
45769
  return `${date4}|${description}|${amount.toFixed(2)}|${type}`;
45737
45770
  }
45771
+ function flagBatchDuplicates(txns) {
45772
+ const seen = new Set;
45773
+ return txns.map((t2) => {
45774
+ const key = dedupeKey(t2.date, t2.description ?? "", t2.amount, t2.type);
45775
+ if (seen.has(key))
45776
+ return true;
45777
+ seen.add(key);
45778
+ return false;
45779
+ });
45780
+ }
45738
45781
  async function importTransactions(client, crypto3, opts) {
45739
45782
  let txns = opts.txns;
45740
45783
  let duplicatesSkipped = 0;
@@ -45764,9 +45807,12 @@ async function importTransactions(client, crypto3, opts) {
45764
45807
  txns = txns.filter((t2) => !seen.has(dedupeKey(t2.date, t2.description ?? "", t2.amount, t2.type)));
45765
45808
  duplicatesSkipped = before - txns.length;
45766
45809
  }
45767
- const rows = txns.map((t2) => {
45810
+ const dupFlags = flagBatchDuplicates(txns);
45811
+ const duplicatesFlagged = dupFlags.filter(Boolean).length;
45812
+ const rows = txns.map((t2, i2) => {
45768
45813
  const enrichedData = settlementEnrichedData(t2.description ?? "", t2.type, opts.source);
45769
- return enrichedData ? { ...t2, enrichedData } : { ...t2 };
45814
+ const base = { ...t2, isDuplicate: dupFlags[i2] };
45815
+ return enrichedData ? { ...base, enrichedData } : base;
45770
45816
  });
45771
45817
  if (crypto3)
45772
45818
  await encryptTransactionFields(rows, crypto3.key);
@@ -45781,7 +45827,7 @@ async function importTransactions(client, crypto3, opts) {
45781
45827
  });
45782
45828
  imported += res.imported ?? 0;
45783
45829
  }
45784
- return { imported, duplicatesSkipped };
45830
+ return { imported, duplicatesSkipped, duplicatesFlagged };
45785
45831
  }
45786
45832
  async function runRescan(client, crypto3) {
45787
45833
  const EMPTY_BAG2 = {
@@ -46265,5 +46311,5 @@ main().catch((err) => {
46265
46311
  process.exit(1);
46266
46312
  });
46267
46313
 
46268
- //# debugId=8B15D0182D36A5DF64756E2164756E21
46314
+ //# debugId=0561A150F92599BE64756E2164756E21
46269
46315
  //# sourceMappingURL=index.js.map