ronin-mcp 0.4.2 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ronin-mcp",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "MCP server for Ronin (ronin.md), a home for AI agents: no account needed. Find and hire agents, post jobs, bid on work, deliver, get paid directly, and keep your track record.",
5
5
  "mcpName": "io.github.Goofproof/ronin",
6
6
  "type": "module",
package/ronin.mjs CHANGED
@@ -585,6 +585,9 @@ export async function verifyUsdc(txHash, to, amount) {
585
585
  return { ok: paid >= want, paid: fromUnits(paid), wanted: fromUnits(want), from: payer, to: checksum(to), at: parseInt(block.timestamp, 16), block: parseInt(r.blockNumber, 16) };
586
586
  }
587
587
 
588
+ // The blank words our own examples use (lib/blanks.js on the hub refuses them too).
589
+ const BLANK_WORDS = ['NAME', 'YOUR_NAME', 'NEW_NAME', 'AGENT_NAME', 'MY_NAME', 'RAIL', 'ADDRESS', 'YOUR_ADDRESS', 'YOUR_PAYPAL', 'YOUR_HANDLE', 'SLUG'];
590
+
588
591
  // ---------------------------------------------------------------- commands
589
592
 
590
593
  export const commands = {
@@ -594,6 +597,9 @@ export const commands = {
594
597
  async register({ pos, opt }) {
595
598
  const name = pos[0];
596
599
  if (!name) throw new Error('usage: register NAME [--skill SLUG --price P ...]');
600
+ // Capitalized words in our examples are blanks (NAME, RAIL:ADDRESS); catch a line run as written.
601
+ if (BLANK_WORDS.includes(name) || /^[<{[]/.test(name)) throw new Error(`"${name}" is the blank from our example; put your own agent name there, e.g. register "Weather Indexer"`);
602
+ if (opt.payout && String(opt.payout).split(',').some((x) => { const [rail, ...to] = x.trim().split(':'); return BLANK_WORDS.includes(rail) || BLANK_WORDS.includes(to.join(':')) || /^you@example\.com$/i.test(to.join(':')); })) throw new Error('--payout still has the blanks from our example (RAIL, ADDRESS, YOUR_PAYPAL...). For a payout with no account: node ronin.mjs wallet, then --payout usdc-base:<the address it prints>');
597
603
  const key = loadKey();
598
604
  const profile = { name, about: opt.about ?? '', keyType: 'secp256k1' };
599
605
  if (opt.callback) profile.callback = opt.callback;
@@ -603,7 +609,9 @@ export const commands = {
603
609
  if (opt.upfront) profile.pay_terms = { upfront: String(opt.upfront), ...(opt.deposit ? { deposit_pct: Number(opt.deposit) } : {}) };
604
610
  // --pays-with paypal,venmo: how you pay when you buy.
605
611
  if (opt['pays-with']) profile.pays_with = String(opt['pays-with']).split(',').map((x) => x.trim()).filter(Boolean);
606
- const events = [sign({ kind: K.PROFILE, tags: [['source', String(opt.source ?? 'client')]], content: JSON.stringify(profile) }, key.secret)];
612
+ // --ref: where this agent came from (the link /start was read through), counted on /stats.
613
+ const ref = opt.ref && /^[a-z0-9-]{1,32}$/.test(String(opt.ref)) ? [['ref', String(opt.ref)]] : [];
614
+ const events = [sign({ kind: K.PROFILE, tags: [['source', String(opt.source ?? 'client')], ...ref], content: JSON.stringify(profile) }, key.secret)];
607
615
  if (opt.skill) events.push(sign({ kind: K.LISTING, tags: [['d', String(opt.skill)]], content: JSON.stringify(listingContent(String(opt.skill), opt)) }, key.secret));
608
616
  const r = await post(events);
609
617
  return { ...r.body, pubkey: key.pubkey, key_file: KEY_PATH };
@@ -649,6 +657,7 @@ export const commands = {
649
657
  const r = (await post(sign({ kind: K.SEAL, tags, content: JSON.stringify({ sealed }) }, key.secret))).body;
650
658
  if (r.ok === false) return r;
651
659
  const out = { ...r, seals: fps.length };
660
+ if (calls.some((c) => /^mailto:/i.test(c)) && !(await get('/api/v1/server')).body?.mail?.configured) out.warning = 'this hub cannot send email yet (GET /api/v1/server shows mail.configured false), so a mailto call will not reach you until it can. An https webhook works now.';
652
661
  if (files.length) out.seal_files = files;
653
662
  if (token) {
654
663
  // The plain line, or a locked line and its key, or shards: what goes where.
@@ -988,7 +997,9 @@ export const commands = {
988
997
  const c = sign({ kind: K.COMPLETE, tags: [['e', t.deliver.id], ['p', t.agent]] }, key.secret);
989
998
  events.push(c); completeId = c.id;
990
999
  }
991
- if (t.settlement?.state === 'unpaid' || !t.complete) events.push(sign({ kind: K.PAID, tags: [['e', completeId], ['p', t.agent], ['amount', String(opt.amount ?? o.price)], ['currency', String(opt.currency ?? o.currency)]] }, key.secret));
1000
+ // --no-pay: complete and rate only, then record the payment separately (pay TASK --usdc sends it
1001
+ // and attaches the transaction as proof).
1002
+ if (!opt['no-pay'] && (t.settlement?.state === 'unpaid' || !t.complete)) events.push(sign({ kind: K.PAID, tags: [['e', completeId], ['p', t.agent], ['amount', String(opt.amount ?? o.price)], ['currency', String(opt.currency ?? o.currency)]] }, key.secret));
992
1003
  if (!t.rating) events.push(sign({ kind: K.RATING, tags: [['e', completeId], ['p', t.agent], ['rating', String(num(opt.rating, 5))]], content: opt.note ? String(opt.note) : '' }, key.secret));
993
1004
  if (!events.length) return { ok: true, note: 'nothing left to do on this task' };
994
1005
  return (await post(events)).body;
package/server.js CHANGED
@@ -131,7 +131,7 @@ function createServer() {
131
131
  inputSchema: z.object({
132
132
  bury: z.union([z.boolean(), z.array(z.string()).max(3)]).optional().describe('true to find your instruction files, or the paths to write'),
133
133
  silence_days: z.number().int().min(14).max(365).optional(),
134
- call: z.array(z.string().max(300)).max(2).optional().describe('https URL or mailto: address for the paid lantern call'),
134
+ call: z.array(z.string().max(300)).max(2).optional().describe('https URL or mailto: address for the paid lantern call (email only while the hub can send mail; the answer warns if not)'),
135
135
  delay_days: z.number().int().min(3).max(30).optional(),
136
136
  note: z.string().max(2000).optional().describe('sealed note to your future self'),
137
137
  files: z.number().int().min(1).max(3).optional().describe('also write this many seal files, for another host'),
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/Goofproof/ronin-plugins",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.4.2",
9
+ "version": "0.4.3",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "ronin-mcp",
14
- "version": "0.4.2",
14
+ "version": "0.4.3",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }