@priors/mcp 0.1.1 → 0.1.3

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
@@ -25,7 +25,7 @@ repaying.
25
25
  | `wallet_balance(address?)` | USDG and gas ETH of the wallet (or any address) | no (with `address`) |
26
26
  | `credit_status(agent_id?)` | line, drawn, available, backer, record, score, open loans and due dates | no (with `agent_id`) |
27
27
  | `borrow(amount_usd, days, dry_run?)` | borrow USDG from the line into the wallet; both amounts required; `dry_run` quotes the fee | yes |
28
- | `repay(loan_id? \| all)` | repay one loan, or every open loan earliest due first | yes |
28
+ | `repay(loan_id? \| all)` | repay one of the agent's own loans, or all of them earliest due first; another agent's loan is refused | yes |
29
29
  | `score_of(agent_id)` | any agent's score (0 to 1000) and repayment record | no |
30
30
  | `find_services(query?)` | services registered with the Priors facilitator that accept USDG (`GET /merchants`) | no |
31
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@priors/mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "MCP server for Priors on Robinhood Chain: pay x402 URLs in USDG, read balances, credit lines and scores, borrow and repay. Key from PRIORS_KEY only.",
6
6
  "type": "module",
package/src/server.mjs CHANGED
@@ -28,7 +28,7 @@ async function loadX402() {
28
28
  }
29
29
  const { X, C } = await loadX402();
30
30
 
31
- export const VERSION = "0.1.0";
31
+ export const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
32
32
  const ADDRESSES = JSON.parse(readFileSync(new URL("../deployments/4663.v2.json", import.meta.url), "utf8"));
33
33
  const DEFAULT_PAY_MAX_USD = 0.1;
34
34
 
@@ -89,6 +89,7 @@ export async function createPriorsMcpServer({ env = process.env, fetchImpl = glo
89
89
  quote: (id, amount, term) => C.quoteBorrow(contracts, id, amount, term),
90
90
  borrow: (id, amount, term) => C.borrowLine(contracts, wallet, id, amount, term),
91
91
  repay: (loanId) => C.repayLoan(contracts, wallet, loanId),
92
+ loanAgent: async (loanId) => (await contracts.pool.getLoan(loanId)).agentId,
92
93
  isController: (id, addr) => contracts.pool.isController(id, addr),
93
94
  agentsOf: (addr) => discoverAgents(addr),
94
95
  };
@@ -274,7 +275,7 @@ export async function createPriorsMcpServer({ env = process.env, fetchImpl = glo
274
275
  // ---- repay ---------------------------------------------------------------------------------------------------
275
276
  tool("repay", {
276
277
  title: "Repay Priors loans",
277
- description: "Repay the agent's Priors loans in full (principal + fee) from the configured wallet's USDG. Give either loan_id for one loan, or all: true to repay every open loan, earliest due first, as far as the balance covers. Moves real money: state the amounts (credit_status lists them) to the user first.",
278
+ description: "Repay the agent's own Priors loans in full (principal + fee) from the configured wallet's USDG; a loan of another agent is refused. Give either loan_id for one loan, or all: true to repay every open loan, earliest due first, as far as the balance covers. Moves real money: state the amounts (credit_status lists them) to the user first.",
278
279
  inputSchema: {
279
280
  loan_id: z.number().int().nonnegative().optional().describe("The loan to repay."),
280
281
  all: z.boolean().optional().describe("true: repay every open loan of the agent, earliest due first."),
@@ -283,11 +284,16 @@ export async function createPriorsMcpServer({ env = process.env, fetchImpl = glo
283
284
  }, async ({ loan_id, all }) => {
284
285
  needWallet("repay");
285
286
  if ((loan_id === undefined) === (all !== true)) throw new ToolError("Give exactly one of loan_id or all: true.");
287
+ // Only the loans of an agent this wallet controls: the pool lets anyone repay any loan, and this wallet's USDG is
288
+ // not for others. PRIORS_AGENT_ID alone is not proof: a stale or mistyped id would point at someone else's agent.
289
+ const id = await resolveAgent();
290
+ await needController(id);
286
291
  if (loan_id !== undefined) {
292
+ const owner = BigInt(await credit.loanAgent(BigInt(loan_id)));
293
+ if (owner !== id) throw new ToolError(`loan #${loan_id} belongs to agent #${owner}, not to agent #${id}. This tool only repays the configured agent's own loans.`);
287
294
  const r = await credit.repay(BigInt(loan_id));
288
295
  return `Repaid loan #${r.loanId} of agent #${r.agentId}: ${usd(r.paid)} (principal + fee). Tx ${r.hash}.`;
289
296
  }
290
- const id = await resolveAgent();
291
297
  const s = await credit.status(id);
292
298
  if (s.openLoans.length === 0) return `Agent #${id} has no open loan. Nothing was repaid.`;
293
299
  const done = [], left = [];