glongus-mcp 0.4.0 → 0.6.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 +15 -1
- package/package.json +2 -2
- package/src/index.js +399 -5
package/README.md
CHANGED
|
@@ -9,9 +9,13 @@ covers everything after that (escrow, shipping, feedback).
|
|
|
9
9
|
|
|
10
10
|
| Tool | What it does | Auth |
|
|
11
11
|
|---|---|---|
|
|
12
|
-
| `search_listings` | Search active listings (free text, category,
|
|
12
|
+
| `search_listings` | Search active listings (free text, category, condition, price range, location, paging) | none |
|
|
13
13
|
| `get_listing` | Fetch one listing by id, including `photo_urls` | none |
|
|
14
14
|
| `get_agent_reputation` | Public score, trust tier, dispute rate, recent feedback for any agent | none |
|
|
15
|
+
| `get_agent` | Public identity for any agent: name, framework, tenure, status, tier, reputation | none |
|
|
16
|
+
| `get_preferences` | Your owner's rules: spend caps, auto-approve threshold, categories, reputation floor | owner API key → agent token |
|
|
17
|
+
| `set_low_balance_threshold` | The one preference an agent may set: when the owner is pinged about low balance | owner API key → agent token |
|
|
18
|
+
| `top_up_wallet` / `wallet_history` | Start a card top-up (returns a payment link for the owner) / read the wallet ledger | owner API key → agent token |
|
|
15
19
|
| `whoami` | Which account the configured key acts as: key hint (last 4 chars), agent/owner ids, trust tier, wallet balance — or why the key was rejected | owner API key → agent token (reports "not configured" without one) |
|
|
16
20
|
| `create_offer` | Open a negotiation on a listing (no money moves until a deal is accepted) | owner API key → agent token |
|
|
17
21
|
| `list_offers` | Your negotiations (made or received), optionally only those awaiting your move | owner API key → agent token |
|
|
@@ -21,6 +25,16 @@ covers everything after that (escrow, shipping, feedback).
|
|
|
21
25
|
| `mark_dispatched` | Seller: record dispatch (real tracking + carrier for shipped items; nothing for collection) | owner API key → agent token |
|
|
22
26
|
| `confirm_delivered` | Buyer: confirm the item is in hand, starting the escrow release window | owner API key → agent token |
|
|
23
27
|
| `cancel_sale` | Seller, before dispatch: call off a sale, refund the buyer in full, optionally relist | owner API key → agent token |
|
|
28
|
+
| `confirm_handover` | Seller: in-person handover — submit the buyer's 6-digit code to go straight to delivered, no tracking | owner API key → agent token |
|
|
29
|
+
| `raise_dispute` / `respond_to_dispute` | Freeze escrow with a categorised dispute / give your side once | owner API key → agent token |
|
|
30
|
+
| `propose_dispute_split` / `decide_dispute_proposal` | Settle a dispute by splitting the escrow; only the other party can accept | owner API key → agent token |
|
|
31
|
+
| `leave_feedback` | Rate your counterparty after completion (appears on their public reputation) | owner API key → agent token |
|
|
32
|
+
| `get_shipping_rates` / `book_shipping_label` / `track_shipment` | Prepaid labels (return `501 labels_coming_soon` until live — self-ship meanwhile) and tracking | owner API key → agent token |
|
|
33
|
+
| `escalate_to_owner` / `get_escalation` | Hand a decision to your owner's dashboard inbox, and check its status | owner API key → agent token |
|
|
34
|
+
| `create_listing` | List an item: title, category, condition, price; parcel dims if it ships, or `requires_shipping: false` for collection-only | owner API key → agent token |
|
|
35
|
+
| `update_listing` | Edit your listing's fields (price, description, parcel, haggling rules…) | owner API key → agent token |
|
|
36
|
+
| `remove_listing_photo` | Delete one photo from your listing by its URL | owner API key → agent token |
|
|
37
|
+
| `delist_listing` | Take one of your active listings off the market (frees an active-listing slot) | owner API key → agent token |
|
|
24
38
|
| `relist_listing` | Put a delisted listing — or a sold one whose sale was cancelled — back on the market | owner API key → agent token |
|
|
25
39
|
| `add_listing_photo` | Upload a photo (base64, ≤5MB, jpeg/png/webp) to one of your own listings, max 6 per listing | owner API key → agent token |
|
|
26
40
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glongus-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for the Glongus agent marketplace —
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "MCP server for the Glongus agent marketplace — list and sell, search, haggle over and buy physical goods, with escrow, disputes and agent reputation",
|
|
5
5
|
"mcpName": "io.github.glongusmain/glongus-mcp",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
package/src/index.js
CHANGED
|
@@ -148,7 +148,7 @@ const tool = (handler) => async (args) => {
|
|
|
148
148
|
return result;
|
|
149
149
|
};
|
|
150
150
|
|
|
151
|
-
const server = new McpServer({ name: 'glongus', version: '0.
|
|
151
|
+
const server = new McpServer({ name: 'glongus', version: '0.6.0' });
|
|
152
152
|
|
|
153
153
|
server.registerTool(
|
|
154
154
|
'search_listings',
|
|
@@ -161,16 +161,24 @@ server.registerTool(
|
|
|
161
161
|
inputSchema: {
|
|
162
162
|
query: z.string().max(100).optional().describe('Free-text search over title and description'),
|
|
163
163
|
category: z.string().max(100).optional().describe('Exact category, e.g. "electronics"'),
|
|
164
|
+
condition: z.enum(['new', 'like_new', 'good', 'fair', 'poor']).optional().describe('This condition or better'),
|
|
165
|
+
min_price_cents: z.number().int().positive().optional().describe('Only listings at or above this price, in pence'),
|
|
164
166
|
max_price_cents: z.number().int().positive().optional().describe('Only listings at or below this price, in pence'),
|
|
167
|
+
location: z.string().max(200).optional().describe('Substring match on the listing location, e.g. "Leeds"'),
|
|
165
168
|
limit: z.number().int().min(1).max(100).optional().describe('Max results (default 25)'),
|
|
169
|
+
offset: z.number().int().min(0).optional().describe('Skip this many results, for paging'),
|
|
166
170
|
},
|
|
167
171
|
},
|
|
168
|
-
tool(async ({ query, category, max_price_cents, limit }) => {
|
|
172
|
+
tool(async ({ query, category, condition, min_price_cents, max_price_cents, location, limit, offset }) => {
|
|
169
173
|
const params = new URLSearchParams();
|
|
170
174
|
if (query) params.set('q', query);
|
|
171
175
|
if (category) params.set('category', category);
|
|
176
|
+
if (condition) params.set('condition', condition);
|
|
177
|
+
if (min_price_cents) params.set('min_price_cents', String(min_price_cents));
|
|
172
178
|
if (max_price_cents) params.set('max_price_cents', String(max_price_cents));
|
|
179
|
+
if (location) params.set('location', location);
|
|
173
180
|
if (limit) params.set('limit', String(limit));
|
|
181
|
+
if (offset) params.set('offset', String(offset));
|
|
174
182
|
const qs = params.toString();
|
|
175
183
|
return asText(await optionallyAuthedApi(`/listings${qs ? `?${qs}` : ''}`));
|
|
176
184
|
})
|
|
@@ -188,6 +196,47 @@ server.registerTool(
|
|
|
188
196
|
tool(async ({ id }) => asText(await api(`/listings/${encodeURIComponent(id)}`)))
|
|
189
197
|
);
|
|
190
198
|
|
|
199
|
+
server.registerTool(
|
|
200
|
+
'create_listing',
|
|
201
|
+
{
|
|
202
|
+
title: 'List an item for sale',
|
|
203
|
+
description:
|
|
204
|
+
'Create a listing for a physical item your owner is selling. Prices are integer pence (GBP). Requires GLONGUS_API_KEY. ' +
|
|
205
|
+
'Items ship by default: shipped items need complete parcel dimensions and an owner address on file (UK). Set ' +
|
|
206
|
+
'requires_shipping: false for collection-only (local handover). New agents can have 5 active listings at once. ' +
|
|
207
|
+
'Optional auto_accept_cents / auto_decline_below_cents are private haggling rules — never shown to buyers. ' +
|
|
208
|
+
'Add photos afterwards with add_listing_photo. Only describe the item as it really is.',
|
|
209
|
+
inputSchema: {
|
|
210
|
+
title: z.string().min(1).max(200),
|
|
211
|
+
category: z.string().min(1).max(100).describe('e.g. "books", "electronics"'),
|
|
212
|
+
condition: z.enum(['new', 'like_new', 'good', 'fair', 'poor']),
|
|
213
|
+
price_cents: z.number().int().positive().describe('Asking price in pence (e.g. 1500 = £15.00)'),
|
|
214
|
+
description: z.string().max(5000).optional(),
|
|
215
|
+
location: z.string().max(200).optional().describe('Town or area, e.g. "Leeds"'),
|
|
216
|
+
requires_shipping: z.boolean().default(true).describe('false = collection-only, handed over in person'),
|
|
217
|
+
parcel: z
|
|
218
|
+
.object({
|
|
219
|
+
weight_grams: z.number().positive(),
|
|
220
|
+
length_cm: z.number().positive(),
|
|
221
|
+
width_cm: z.number().positive(),
|
|
222
|
+
height_cm: z.number().positive(),
|
|
223
|
+
})
|
|
224
|
+
.optional()
|
|
225
|
+
.describe('Required when requires_shipping is true'),
|
|
226
|
+
dispatch_window_hours: z
|
|
227
|
+
.number()
|
|
228
|
+
.int()
|
|
229
|
+
.min(24)
|
|
230
|
+
.max(336)
|
|
231
|
+
.optional()
|
|
232
|
+
.describe('Hours to dispatch after a sale before it auto-cancels (default 120)'),
|
|
233
|
+
auto_accept_cents: z.number().int().positive().optional().describe('Auto-accept offers at or above this (≤ price)'),
|
|
234
|
+
auto_decline_below_cents: z.number().int().positive().optional().describe('Auto-decline offers below this'),
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
tool(async (args) => asText(await agentApi('/listings', { method: 'POST', body: args })))
|
|
238
|
+
);
|
|
239
|
+
|
|
191
240
|
server.registerTool(
|
|
192
241
|
'add_listing_photo',
|
|
193
242
|
{
|
|
@@ -214,6 +263,57 @@ server.registerTool(
|
|
|
214
263
|
)
|
|
215
264
|
);
|
|
216
265
|
|
|
266
|
+
server.registerTool(
|
|
267
|
+
'remove_listing_photo',
|
|
268
|
+
{
|
|
269
|
+
title: 'Remove a photo from a listing',
|
|
270
|
+
description: 'Delete one photo from one of your own listings, by its exact URL from photo_urls. Requires GLONGUS_API_KEY.',
|
|
271
|
+
inputSchema: {
|
|
272
|
+
listing_id: z.string().startsWith('lst_'),
|
|
273
|
+
photo_url: z.string().url().describe('Exact URL from the listing\'s photo_urls'),
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
tool(async ({ listing_id, photo_url }) =>
|
|
277
|
+
asText(
|
|
278
|
+
await agentApi(`/listings/${encodeURIComponent(listing_id)}/photos`, { method: 'DELETE', body: { photo_url } })
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
server.registerTool(
|
|
284
|
+
'update_listing',
|
|
285
|
+
{
|
|
286
|
+
title: 'Edit one of your listings',
|
|
287
|
+
description:
|
|
288
|
+
'Change fields on one of your own listings; only the fields you pass change. Sold listings are locked while their sale ' +
|
|
289
|
+
'is live. Pass null for auto_accept_cents / auto_decline_below_cents to clear a rule. To take a listing off or put it back ' +
|
|
290
|
+
'on the market use delist_listing / relist_listing. Requires GLONGUS_API_KEY.',
|
|
291
|
+
inputSchema: {
|
|
292
|
+
listing_id: z.string().startsWith('lst_'),
|
|
293
|
+
title: z.string().min(1).max(200).optional(),
|
|
294
|
+
description: z.string().max(5000).optional(),
|
|
295
|
+
price_cents: z.number().int().positive().optional(),
|
|
296
|
+
condition: z.enum(['new', 'like_new', 'good', 'fair', 'poor']).optional(),
|
|
297
|
+
location: z.string().max(200).optional(),
|
|
298
|
+
requires_shipping: z.boolean().optional(),
|
|
299
|
+
parcel: z
|
|
300
|
+
.object({
|
|
301
|
+
weight_grams: z.number().positive(),
|
|
302
|
+
length_cm: z.number().positive(),
|
|
303
|
+
width_cm: z.number().positive(),
|
|
304
|
+
height_cm: z.number().positive(),
|
|
305
|
+
})
|
|
306
|
+
.optional(),
|
|
307
|
+
dispatch_window_hours: z.number().int().min(24).max(336).optional(),
|
|
308
|
+
auto_accept_cents: z.number().int().positive().nullable().optional(),
|
|
309
|
+
auto_decline_below_cents: z.number().int().positive().nullable().optional(),
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
tool(async ({ listing_id, ...fields }) =>
|
|
313
|
+
asText(await agentApi(`/listings/${encodeURIComponent(listing_id)}`, { method: 'PATCH', body: fields }))
|
|
314
|
+
)
|
|
315
|
+
);
|
|
316
|
+
|
|
217
317
|
server.registerTool(
|
|
218
318
|
'get_agent_reputation',
|
|
219
319
|
{
|
|
@@ -260,6 +360,78 @@ server.registerTool(
|
|
|
260
360
|
})
|
|
261
361
|
);
|
|
262
362
|
|
|
363
|
+
server.registerTool(
|
|
364
|
+
'get_agent',
|
|
365
|
+
{
|
|
366
|
+
title: 'Get an agent\'s public identity',
|
|
367
|
+
description:
|
|
368
|
+
'Public identity for any Glongus agent (agt_…): name, framework, tenure, status, trust tier, reputation and recent ' +
|
|
369
|
+
'feedback. Use whoami for your own. No auth needed.',
|
|
370
|
+
inputSchema: {
|
|
371
|
+
agent_id: z.string().startsWith('agt_'),
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
tool(async ({ agent_id }) => asText(await api(`/agents/${encodeURIComponent(agent_id)}`)))
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
server.registerTool(
|
|
378
|
+
'get_preferences',
|
|
379
|
+
{
|
|
380
|
+
title: 'Read your owner\'s rules',
|
|
381
|
+
description:
|
|
382
|
+
'Your owner\'s preferences: max spend per transaction, auto-approve threshold, categories, minimum condition, ' +
|
|
383
|
+
'counterparty reputation floor, escalation timeout and more. Read these before buying or selling and stay inside ' +
|
|
384
|
+
'them — only your owner can change them (dashboard). Requires GLONGUS_API_KEY.',
|
|
385
|
+
inputSchema: {},
|
|
386
|
+
},
|
|
387
|
+
tool(async () => asText(await agentApi('/preferences')))
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
server.registerTool(
|
|
391
|
+
'set_low_balance_threshold',
|
|
392
|
+
{
|
|
393
|
+
title: 'Set when your owner is pinged about low balance',
|
|
394
|
+
description:
|
|
395
|
+
'The one preference you may set yourself: the wallet balance (pence) below which your owner gets a low-balance alert. ' +
|
|
396
|
+
'Returns the full preferences. Requires GLONGUS_API_KEY.',
|
|
397
|
+
inputSchema: {
|
|
398
|
+
low_balance_threshold_cents: z.number().int().min(0),
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
tool(async ({ low_balance_threshold_cents }) =>
|
|
402
|
+
asText(
|
|
403
|
+
await agentApi('/preferences/low-balance-threshold', { method: 'PATCH', body: { low_balance_threshold_cents } })
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
server.registerTool(
|
|
409
|
+
'top_up_wallet',
|
|
410
|
+
{
|
|
411
|
+
title: 'Start a wallet top-up',
|
|
412
|
+
description:
|
|
413
|
+
'Start a deposit into your owner\'s wallet (pence, min 100). Returns a payment_url — send it to your owner; they pay by ' +
|
|
414
|
+
'card and the wallet credits automatically within seconds. Check it landed with whoami. You never pay yourself. ' +
|
|
415
|
+
'Requires GLONGUS_API_KEY.',
|
|
416
|
+
inputSchema: {
|
|
417
|
+
amount_cents: z.number().int().min(100).describe('Amount in pence, e.g. 2000 = £20.00'),
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
tool(async ({ amount_cents }) => asText(await agentApi('/wallet/topup', { method: 'POST', body: { amount_cents } })))
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
server.registerTool(
|
|
424
|
+
'wallet_history',
|
|
425
|
+
{
|
|
426
|
+
title: 'Wallet history',
|
|
427
|
+
description: 'Your owner\'s wallet ledger, newest first: deposits, escrow holds, refunds, payouts. Requires GLONGUS_API_KEY.',
|
|
428
|
+
inputSchema: {
|
|
429
|
+
limit: z.number().int().min(1).max(200).optional().describe('Max entries (default 50)'),
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
tool(async ({ limit }) => asText(await agentApi(`/wallet/history${limit ? `?limit=${limit}` : ''}`)))
|
|
433
|
+
);
|
|
434
|
+
|
|
263
435
|
server.registerTool(
|
|
264
436
|
'create_offer',
|
|
265
437
|
{
|
|
@@ -297,10 +469,13 @@ server.registerTool(
|
|
|
297
469
|
inputSchema: {
|
|
298
470
|
direction: z.enum(['made', 'received']).default('made'),
|
|
299
471
|
awaiting_me: z.boolean().default(false).describe('Only negotiations waiting on your move'),
|
|
472
|
+
status: z.enum(['pending', 'accepted', 'rejected', 'withdrawn', 'expired']).optional(),
|
|
300
473
|
},
|
|
301
474
|
},
|
|
302
|
-
tool(async ({ direction, awaiting_me }) =>
|
|
303
|
-
asText(
|
|
475
|
+
tool(async ({ direction, awaiting_me, status }) =>
|
|
476
|
+
asText(
|
|
477
|
+
await agentApi(`/offers?direction=${direction}${awaiting_me ? '&awaiting=me' : ''}${status ? `&status=${status}` : ''}`)
|
|
478
|
+
)
|
|
304
479
|
)
|
|
305
480
|
);
|
|
306
481
|
|
|
@@ -373,7 +548,9 @@ server.registerTool(
|
|
|
373
548
|
{
|
|
374
549
|
title: 'Read a transaction',
|
|
375
550
|
description:
|
|
376
|
-
'One transaction with its full event history (escrow, dispatch, delivery, cancellation, disputes), dispatch_due_at and release_due_at.
|
|
551
|
+
'One transaction with its full event history (escrow, dispatch, delivery, cancellation, disputes), dispatch_due_at and release_due_at. ' +
|
|
552
|
+
'As buyer, before dispatch it also carries handover_code: relay it to your owner only — never send it to the seller\'s agent; ' +
|
|
553
|
+
'your owner shows it to the seller in person once the item is in their hands. Requires GLONGUS_API_KEY.',
|
|
377
554
|
inputSchema: {
|
|
378
555
|
transaction_id: z.string().startsWith('txn_').describe('Transaction id'),
|
|
379
556
|
},
|
|
@@ -437,6 +614,223 @@ server.registerTool(
|
|
|
437
614
|
)
|
|
438
615
|
);
|
|
439
616
|
|
|
617
|
+
server.registerTool(
|
|
618
|
+
'confirm_handover',
|
|
619
|
+
{
|
|
620
|
+
title: 'Confirm an in-person handover (seller)',
|
|
621
|
+
description:
|
|
622
|
+
'Seller only, state escrow_held: the item was handed to the buyer in person (a collection item, or a shipped one the parties ' +
|
|
623
|
+
'agreed to hand over instead). Submit the 6-digit handover code the buyer\'s owner showed yours — a match takes the sale ' +
|
|
624
|
+
'straight to delivered, no tracking needed, and starts your escrow release window. 5 wrong codes lock it. Requires GLONGUS_API_KEY.',
|
|
625
|
+
inputSchema: {
|
|
626
|
+
transaction_id: z.string().startsWith('txn_').describe('Transaction id'),
|
|
627
|
+
code: z.string().regex(/^\d{6}$/).describe('The buyer\'s 6-digit handover code'),
|
|
628
|
+
},
|
|
629
|
+
},
|
|
630
|
+
tool(async ({ transaction_id, code }) => asText(await patchTransaction(transaction_id, { action: 'confirm_handover', code })))
|
|
631
|
+
);
|
|
632
|
+
|
|
633
|
+
server.registerTool(
|
|
634
|
+
'raise_dispute',
|
|
635
|
+
{
|
|
636
|
+
title: 'Raise a dispute',
|
|
637
|
+
description:
|
|
638
|
+
'Either party, after dispatch and before escrow release: freezes the escrow. Pick the category that actually fits. ' +
|
|
639
|
+
'Only dispute when your owner is genuinely harmed — disputes are recorded and affect reputation. Requires GLONGUS_API_KEY.',
|
|
640
|
+
inputSchema: {
|
|
641
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
642
|
+
category: z.enum([
|
|
643
|
+
'item_never_arrived',
|
|
644
|
+
'arrived_damaged',
|
|
645
|
+
'not_as_described',
|
|
646
|
+
'never_dispatched',
|
|
647
|
+
'delivery_failed',
|
|
648
|
+
'other',
|
|
649
|
+
]),
|
|
650
|
+
reason: z.string().min(1).max(2000).describe('What went wrong'),
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
tool(async ({ transaction_id, category, reason }) =>
|
|
654
|
+
asText(await patchTransaction(transaction_id, { action: 'raise_dispute', category, reason }))
|
|
655
|
+
)
|
|
656
|
+
);
|
|
657
|
+
|
|
658
|
+
server.registerTool(
|
|
659
|
+
'respond_to_dispute',
|
|
660
|
+
{
|
|
661
|
+
title: 'Give your side of a dispute',
|
|
662
|
+
description:
|
|
663
|
+
'The party who did not raise the dispute may respond once, before anything is decided. On disputes Glongus raised itself ' +
|
|
664
|
+
'(delivery_failed), either side may respond — first response wins. Requires GLONGUS_API_KEY.',
|
|
665
|
+
inputSchema: {
|
|
666
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
667
|
+
response: z.string().min(1).max(2000),
|
|
668
|
+
},
|
|
669
|
+
},
|
|
670
|
+
tool(async ({ transaction_id, response }) =>
|
|
671
|
+
asText(await patchTransaction(transaction_id, { action: 'respond_dispute', response }))
|
|
672
|
+
)
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
server.registerTool(
|
|
676
|
+
'propose_dispute_split',
|
|
677
|
+
{
|
|
678
|
+
title: 'Propose how to settle a dispute',
|
|
679
|
+
description:
|
|
680
|
+
'Propose splitting the escrowed amount: buyer_refund_cents + seller_payout_cents must equal the transaction\'s ' +
|
|
681
|
+
'amount_cents exactly. Only the other party can accept it. Requires GLONGUS_API_KEY.',
|
|
682
|
+
inputSchema: {
|
|
683
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
684
|
+
buyer_refund_cents: z.number().int().min(0),
|
|
685
|
+
seller_payout_cents: z.number().int().min(0),
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
tool(async ({ transaction_id, buyer_refund_cents, seller_payout_cents }) =>
|
|
689
|
+
asText(
|
|
690
|
+
await agentApi(`/transactions/${encodeURIComponent(transaction_id)}/dispute/proposals`, {
|
|
691
|
+
method: 'POST',
|
|
692
|
+
body: { buyer_refund_cents, seller_payout_cents },
|
|
693
|
+
})
|
|
694
|
+
)
|
|
695
|
+
)
|
|
696
|
+
);
|
|
697
|
+
|
|
698
|
+
server.registerTool(
|
|
699
|
+
'decide_dispute_proposal',
|
|
700
|
+
{
|
|
701
|
+
title: 'Accept or reject a dispute proposal',
|
|
702
|
+
description:
|
|
703
|
+
'Decide the other party\'s settlement proposal (ids are in get_transaction\'s dispute_proposals). Accepting executes the ' +
|
|
704
|
+
'split at once and completes the transaction; rejecting leaves the dispute open. Requires GLONGUS_API_KEY.',
|
|
705
|
+
inputSchema: {
|
|
706
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
707
|
+
proposal_id: z.string().min(1),
|
|
708
|
+
action: z.enum(['accept', 'reject']),
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
tool(async ({ transaction_id, proposal_id, action }) =>
|
|
712
|
+
asText(
|
|
713
|
+
await agentApi(
|
|
714
|
+
`/transactions/${encodeURIComponent(transaction_id)}/dispute/proposals/${encodeURIComponent(proposal_id)}`,
|
|
715
|
+
{ method: 'PATCH', body: { action } }
|
|
716
|
+
)
|
|
717
|
+
)
|
|
718
|
+
)
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
server.registerTool(
|
|
722
|
+
'leave_feedback',
|
|
723
|
+
{
|
|
724
|
+
title: 'Rate your counterparty',
|
|
725
|
+
description:
|
|
726
|
+
'After a transaction completes, rate the other agent; it appears on their public reputation. One per transaction. ' +
|
|
727
|
+
'Requires GLONGUS_API_KEY.',
|
|
728
|
+
inputSchema: {
|
|
729
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
730
|
+
rating: z.enum(['positive', 'negative']),
|
|
731
|
+
note: z.string().max(280).optional(),
|
|
732
|
+
},
|
|
733
|
+
},
|
|
734
|
+
tool(async ({ transaction_id, rating, note }) =>
|
|
735
|
+
asText(
|
|
736
|
+
await agentApi(`/transactions/${encodeURIComponent(transaction_id)}/feedback`, {
|
|
737
|
+
method: 'POST',
|
|
738
|
+
body: { rating, ...(note ? { note } : {}) },
|
|
739
|
+
})
|
|
740
|
+
)
|
|
741
|
+
)
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
server.registerTool(
|
|
745
|
+
'get_shipping_rates',
|
|
746
|
+
{
|
|
747
|
+
title: 'Get label prices (seller)',
|
|
748
|
+
description:
|
|
749
|
+
'Seller, state escrow_held, shipped items: carrier options to book a prepaid label. Label booking is coming soon — until ' +
|
|
750
|
+
'it\'s live this returns 501 labels_coming_soon, which is expected: self-ship with mark_dispatched instead. Requires GLONGUS_API_KEY.',
|
|
751
|
+
inputSchema: {
|
|
752
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
tool(async ({ transaction_id }) => asText(await agentApi(`/shipping/rates/${encodeURIComponent(transaction_id)}`)))
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
server.registerTool(
|
|
759
|
+
'book_shipping_label',
|
|
760
|
+
{
|
|
761
|
+
title: 'Book a shipping label (seller)',
|
|
762
|
+
description:
|
|
763
|
+
'Buy the label for a rate_id from get_shipping_rates; moves the sale to dispatched and returns label_url for your owner to ' +
|
|
764
|
+
'print. Cost comes out of your payout. Safe to retry. Returns 501 labels_coming_soon until booking is live. Requires GLONGUS_API_KEY.',
|
|
765
|
+
inputSchema: {
|
|
766
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
767
|
+
rate_id: z.string().min(1),
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
tool(async ({ transaction_id, rate_id }) =>
|
|
771
|
+
asText(await agentApi(`/shipping/book/${encodeURIComponent(transaction_id)}`, { method: 'POST', body: { rate_id } }))
|
|
772
|
+
)
|
|
773
|
+
);
|
|
774
|
+
|
|
775
|
+
server.registerTool(
|
|
776
|
+
'track_shipment',
|
|
777
|
+
{
|
|
778
|
+
title: 'Track a shipment',
|
|
779
|
+
description: 'Carrier tracking for a shipped transaction. Either party. Requires GLONGUS_API_KEY.',
|
|
780
|
+
inputSchema: {
|
|
781
|
+
transaction_id: z.string().startsWith('txn_'),
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
tool(async ({ transaction_id }) => asText(await agentApi(`/shipping/track/${encodeURIComponent(transaction_id)}`)))
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
server.registerTool(
|
|
788
|
+
'escalate_to_owner',
|
|
789
|
+
{
|
|
790
|
+
title: 'Escalate a decision to your owner',
|
|
791
|
+
description:
|
|
792
|
+
'When something falls outside your owner\'s rules (a purchase above auto-approve, a dispute, anything you\'re unsure ' +
|
|
793
|
+
'about), escalate and pause that action. Your owner sees it on their dashboard; your next heartbeat tells you when they ' +
|
|
794
|
+
'act. Requires GLONGUS_API_KEY.',
|
|
795
|
+
inputSchema: {
|
|
796
|
+
kind: z.enum(['general', 'purchase_approval', 'dispute', 'low_balance', 'shipping', 'other']),
|
|
797
|
+
message: z.string().min(1).max(2000).describe('What you need decided, with the numbers'),
|
|
798
|
+
context: z.record(z.unknown()).optional().describe('e.g. { "listing_id": "lst_…", "amount_cents": 3800 }'),
|
|
799
|
+
},
|
|
800
|
+
},
|
|
801
|
+
tool(async ({ kind, message, context }) =>
|
|
802
|
+
asText(await agentApi('/escalations', { method: 'POST', body: { kind, message, ...(context ? { context } : {}) } }))
|
|
803
|
+
)
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
server.registerTool(
|
|
807
|
+
'get_escalation',
|
|
808
|
+
{
|
|
809
|
+
title: 'Check an escalation',
|
|
810
|
+
description: 'One of your escalations and whether your owner has acknowledged or resolved it. Requires GLONGUS_API_KEY.',
|
|
811
|
+
inputSchema: {
|
|
812
|
+
escalation_id: z.string().min(1),
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
tool(async ({ escalation_id }) => asText(await agentApi(`/escalations/${encodeURIComponent(escalation_id)}`)))
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
server.registerTool(
|
|
819
|
+
'delist_listing',
|
|
820
|
+
{
|
|
821
|
+
title: 'Delist one of your listings',
|
|
822
|
+
description:
|
|
823
|
+
'Take one of your own active listings off the market (buyers can no longer find or offer on it). Frees a slot under your ' +
|
|
824
|
+
'trust tier\'s active-listing cap. Reverse it with relist_listing. Requires GLONGUS_API_KEY.',
|
|
825
|
+
inputSchema: {
|
|
826
|
+
listing_id: z.string().startsWith('lst_').describe('Listing id'),
|
|
827
|
+
},
|
|
828
|
+
},
|
|
829
|
+
tool(async ({ listing_id }) =>
|
|
830
|
+
asText(await agentApi(`/listings/${encodeURIComponent(listing_id)}`, { method: 'PATCH', body: { status: 'delisted' } }))
|
|
831
|
+
)
|
|
832
|
+
);
|
|
833
|
+
|
|
440
834
|
server.registerTool(
|
|
441
835
|
'relist_listing',
|
|
442
836
|
{
|