paisa-mcp 0.0.18 → 0.0.20
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 +69 -13
- package/dist/index.js.map +6 -6
- package/package.json +1 -1
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.
|
|
42485
|
+
const data = await client.put("/api/budgets", body);
|
|
42486
42486
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
42487
42487
|
});
|
|
42488
42488
|
}
|
|
@@ -42554,18 +42554,28 @@ function registerDebtTools(server, client) {
|
|
|
42554
42554
|
dueDate: exports_external.string().optional().describe("YYYY-MM-DD"),
|
|
42555
42555
|
notes: exports_external.string().optional()
|
|
42556
42556
|
}
|
|
42557
|
-
}, async (
|
|
42558
|
-
const
|
|
42557
|
+
}, async ({ name, amount, type, dueDate, notes }) => {
|
|
42558
|
+
const notesWithDue = dueDate ? [notes, `Due: ${dueDate}`].filter(Boolean).join(" — ") : notes;
|
|
42559
|
+
const data = await client.post("/api/debts", {
|
|
42560
|
+
name,
|
|
42561
|
+
direction: type,
|
|
42562
|
+
type: "other",
|
|
42563
|
+
outstandingBalance: amount,
|
|
42564
|
+
...notesWithDue ? { notes: notesWithDue } : {}
|
|
42565
|
+
});
|
|
42559
42566
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
42560
42567
|
});
|
|
42561
42568
|
server.registerTool("settle_debt", {
|
|
42562
|
-
description: "Mark a debt as settled.",
|
|
42569
|
+
description: "Mark a debt as settled (soft-deactivates it; zeroes the balance).",
|
|
42563
42570
|
inputSchema: {
|
|
42564
42571
|
id: exports_external.string(),
|
|
42565
42572
|
settledAmount: exports_external.string().optional().describe("Actual settled amount if different")
|
|
42566
42573
|
}
|
|
42567
|
-
}, async ({ id,
|
|
42568
|
-
const data = await client.patch(`/api/debts/${id}`, {
|
|
42574
|
+
}, async ({ id, settledAmount }) => {
|
|
42575
|
+
const data = await client.patch(`/api/debts/${id}`, {
|
|
42576
|
+
isActive: false,
|
|
42577
|
+
outstandingBalance: settledAmount ?? "0"
|
|
42578
|
+
});
|
|
42569
42579
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
42570
42580
|
});
|
|
42571
42581
|
}
|
|
@@ -42900,9 +42910,9 @@ function registerInvestmentTools(server, client) {
|
|
|
42900
42910
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
42901
42911
|
});
|
|
42902
42912
|
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).",
|
|
42913
|
+
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
42914
|
inputSchema: {
|
|
42905
|
-
type: exports_external.enum(["sip", "fixed_deposit"]).describe("Investment type"),
|
|
42915
|
+
type: exports_external.enum(["sip", "fixed_deposit", "holding"]).describe("Investment type"),
|
|
42906
42916
|
id: exports_external.string().optional().describe("sip: SIP UUID — omit to add, pass to update"),
|
|
42907
42917
|
name: exports_external.string().optional().describe('sip: fund name (e.g. "Parag Parikh Flexi Cap")'),
|
|
42908
42918
|
startDate: exports_external.string().optional().describe("sip & fixed_deposit: YYYY-MM-DD"),
|
|
@@ -42915,10 +42925,43 @@ function registerInvestmentTools(server, client) {
|
|
|
42915
42925
|
interestRate: exports_external.string().optional().describe("fixed_deposit: annual interest rate %"),
|
|
42916
42926
|
maturityDate: exports_external.string().optional().describe("fixed_deposit: YYYY-MM-DD"),
|
|
42917
42927
|
notes: exports_external.string().optional().describe("fixed_deposit: notes"),
|
|
42928
|
+
holdingType: exports_external.enum(["mutual_fund", "stock", "gold", "ppf", "nps", "other"]).optional().describe("holding: asset type"),
|
|
42929
|
+
platform: exports_external.string().optional().describe("holding: broker/platform (e.g. groww); defaults to 'manual'"),
|
|
42930
|
+
symbol: exports_external.string().optional().describe("holding: ticker symbol (optional)"),
|
|
42931
|
+
isin: exports_external.string().optional().describe("holding: ISIN (optional)"),
|
|
42932
|
+
units: exports_external.string().optional().describe("holding: units held (optional)"),
|
|
42933
|
+
investedAmount: exports_external.string().optional().describe("holding: total invested / cost"),
|
|
42934
|
+
currentValue: exports_external.string().optional().describe("holding: current market value"),
|
|
42918
42935
|
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")
|
|
42936
|
+
owner: exports_external.string().optional().describe("sip & fixed_deposit & holding: owner")
|
|
42920
42937
|
}
|
|
42921
42938
|
}, async ({ type, ...fields }) => {
|
|
42939
|
+
if (type === "holding") {
|
|
42940
|
+
const { name, holdingType, owner: owner2, platform, symbol, isin, units, investedAmount } = fields;
|
|
42941
|
+
const { currentValue } = fields;
|
|
42942
|
+
const missing2 = [
|
|
42943
|
+
["name", name],
|
|
42944
|
+
["holdingType", holdingType],
|
|
42945
|
+
["owner", owner2],
|
|
42946
|
+
["investedAmount", investedAmount],
|
|
42947
|
+
["currentValue", currentValue]
|
|
42948
|
+
].filter(([, v]) => v === undefined).map(([k]) => k);
|
|
42949
|
+
if (missing2.length > 0) {
|
|
42950
|
+
throw new Error(`Missing required fields for holding: ${missing2.join(", ")}`);
|
|
42951
|
+
}
|
|
42952
|
+
const data2 = await client.post("/api/investments/holdings", {
|
|
42953
|
+
name,
|
|
42954
|
+
holdingType,
|
|
42955
|
+
owner: owner2,
|
|
42956
|
+
platform: platform ?? "manual",
|
|
42957
|
+
symbol,
|
|
42958
|
+
isin,
|
|
42959
|
+
units,
|
|
42960
|
+
investedAmount,
|
|
42961
|
+
currentValue
|
|
42962
|
+
});
|
|
42963
|
+
return { content: [{ type: "text", text: JSON.stringify(data2) }] };
|
|
42964
|
+
}
|
|
42922
42965
|
if (type === "sip") {
|
|
42923
42966
|
const {
|
|
42924
42967
|
id,
|
|
@@ -45735,6 +45778,16 @@ async function backfillPersons(client, crypto3, opts = {}) {
|
|
|
45735
45778
|
function dedupeKey(date4, description, amount, type) {
|
|
45736
45779
|
return `${date4}|${description}|${amount.toFixed(2)}|${type}`;
|
|
45737
45780
|
}
|
|
45781
|
+
function flagBatchDuplicates(txns) {
|
|
45782
|
+
const seen = new Set;
|
|
45783
|
+
return txns.map((t2) => {
|
|
45784
|
+
const key = dedupeKey(t2.date, t2.description ?? "", t2.amount, t2.type);
|
|
45785
|
+
if (seen.has(key))
|
|
45786
|
+
return true;
|
|
45787
|
+
seen.add(key);
|
|
45788
|
+
return false;
|
|
45789
|
+
});
|
|
45790
|
+
}
|
|
45738
45791
|
async function importTransactions(client, crypto3, opts) {
|
|
45739
45792
|
let txns = opts.txns;
|
|
45740
45793
|
let duplicatesSkipped = 0;
|
|
@@ -45764,9 +45817,12 @@ async function importTransactions(client, crypto3, opts) {
|
|
|
45764
45817
|
txns = txns.filter((t2) => !seen.has(dedupeKey(t2.date, t2.description ?? "", t2.amount, t2.type)));
|
|
45765
45818
|
duplicatesSkipped = before - txns.length;
|
|
45766
45819
|
}
|
|
45767
|
-
const
|
|
45820
|
+
const dupFlags = flagBatchDuplicates(txns);
|
|
45821
|
+
const duplicatesFlagged = dupFlags.filter(Boolean).length;
|
|
45822
|
+
const rows = txns.map((t2, i2) => {
|
|
45768
45823
|
const enrichedData = settlementEnrichedData(t2.description ?? "", t2.type, opts.source);
|
|
45769
|
-
|
|
45824
|
+
const base = { ...t2, isDuplicate: dupFlags[i2] };
|
|
45825
|
+
return enrichedData ? { ...base, enrichedData } : base;
|
|
45770
45826
|
});
|
|
45771
45827
|
if (crypto3)
|
|
45772
45828
|
await encryptTransactionFields(rows, crypto3.key);
|
|
@@ -45781,7 +45837,7 @@ async function importTransactions(client, crypto3, opts) {
|
|
|
45781
45837
|
});
|
|
45782
45838
|
imported += res.imported ?? 0;
|
|
45783
45839
|
}
|
|
45784
|
-
return { imported, duplicatesSkipped };
|
|
45840
|
+
return { imported, duplicatesSkipped, duplicatesFlagged };
|
|
45785
45841
|
}
|
|
45786
45842
|
async function runRescan(client, crypto3) {
|
|
45787
45843
|
const EMPTY_BAG2 = {
|
|
@@ -46265,5 +46321,5 @@ main().catch((err) => {
|
|
|
46265
46321
|
process.exit(1);
|
|
46266
46322
|
});
|
|
46267
46323
|
|
|
46268
|
-
//# debugId=
|
|
46324
|
+
//# debugId=1EEBC94B29D2067F64756E2164756E21
|
|
46269
46325
|
//# sourceMappingURL=index.js.map
|