@stratabook/mcp 0.2.2 → 0.2.5
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 +38 -7
- package/dist/src/server.js +282 -78
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,6 +4,11 @@ Official capability-gated MCP access to Strata and Sonar. The server delegates
|
|
|
4
4
|
to `@stratabook/sdk`: it follows the live capability catalog and contains no
|
|
5
5
|
separate quote or execution logic.
|
|
6
6
|
|
|
7
|
+
The official hosted endpoint currently exposes market, exact-output, and
|
|
8
|
+
asset-to-asset Sonar quotes, together with quote-bound execution tools.
|
|
9
|
+
Capability gating is a runtime safety check so clients stop if policy changes;
|
|
10
|
+
it does **not** mean quotes are inactive.
|
|
11
|
+
|
|
7
12
|
## Local stdio
|
|
8
13
|
|
|
9
14
|
```sh
|
|
@@ -40,6 +45,10 @@ The tools currently available are:
|
|
|
40
45
|
- `strata_portfolio_history`
|
|
41
46
|
- `strata_market_making_status`
|
|
42
47
|
- `strata_market_making_reputation`
|
|
48
|
+
- `strata_market_making_prepare` — start or stop a Strand/Current from a market label, decimal base size, spread, and duration; no arrays or atom conversion
|
|
49
|
+
- `strata_market_making_submit_and_wait` — submit the externally signed preparation idempotently and wait for matching chain-derived state
|
|
50
|
+
- `strata_market_making_strand_prepare`, `strata_market_making_strand_submit`
|
|
51
|
+
- `strata_market_making_current_prepare`, `strata_market_making_current_submit`
|
|
43
52
|
- `strata_vault_status`
|
|
44
53
|
- `strata_vault_setup`, `strata_vault_deposit`, `strata_vault_withdraw`, `strata_vault_delegate`, `strata_vault_policy`, `strata_vault_pause` — prepare owner actions with Strata as sponsored fee payer
|
|
45
54
|
- `strata_vault_submit` — submit the owner-signed preparation; Strata pays and broadcasts
|
|
@@ -50,12 +59,12 @@ The tools currently available are:
|
|
|
50
59
|
- `strata_referral_claim` — prepare externally signable consent or submit the signed claim
|
|
51
60
|
- `strata_bugs`
|
|
52
61
|
- `strata_bug_submit` — prepare externally signable bytes or submit the signed report
|
|
53
|
-
- `strata_markets
|
|
54
|
-
- `strata_quote` and `strata_exact_output_quote` (spend X / receive at least Y)
|
|
55
|
-
- `strata_swap_quote
|
|
56
|
-
- `strata_execution_challenge
|
|
57
|
-
- `strata_execution_prepare
|
|
58
|
-
- `strata_execution_submit
|
|
62
|
+
- `strata_markets`
|
|
63
|
+
- `strata_quote` and `strata_exact_output_quote` — live market quotes (spend X / receive at least Y)
|
|
64
|
+
- `strata_swap_quote` — live catalog-asset swap quotes
|
|
65
|
+
- `strata_execution_challenge`
|
|
66
|
+
- `strata_execution_prepare`
|
|
67
|
+
- `strata_execution_submit`
|
|
59
68
|
- `strata_execution_status` — recover a durable immediate-execution receipt
|
|
60
69
|
- `strata_order_challenge`, when `orders.prepare` is enabled for MCP
|
|
61
70
|
- `strata_order_prepare`, when `orders.prepare` is enabled for MCP
|
|
@@ -72,7 +81,29 @@ available as `strata://platform-graph/v2`.
|
|
|
72
81
|
|
|
73
82
|
The tool list follows the live public policy. Every call rechecks that policy,
|
|
74
83
|
so a disabled capability stops immediately even if a client cached an older
|
|
75
|
-
tool list.
|
|
84
|
+
tool list. Tool discovery from the connected server remains authoritative for
|
|
85
|
+
self-hosted deployments or any future policy change.
|
|
86
|
+
|
|
87
|
+
For normal maker operation, use two calls:
|
|
88
|
+
|
|
89
|
+
1. Call `strata_market_making_prepare` with `action: "start"`, a label such as
|
|
90
|
+
`SOL/USDC`, `product: "current"` or `"strand"`, `spreadBps`, a decimal size
|
|
91
|
+
such as `0.01 SOL`, and the maker wallet. Duration defaults to ten minutes
|
|
92
|
+
and levels default to three.
|
|
93
|
+
2. Verify and sign only `prepared.transaction_base64` in the external wallet,
|
|
94
|
+
then pass it and `prepared.maker_control_id` to
|
|
95
|
+
`strata_market_making_submit_and_wait`.
|
|
96
|
+
|
|
97
|
+
The second call returns only after Strata's chain-derived maker status matches
|
|
98
|
+
the exact product settings. Use `action: "stop"` through the same pair. The
|
|
99
|
+
older product-specific tools remain available for strategies that deliberately
|
|
100
|
+
manage every low-level array and safety field.
|
|
101
|
+
|
|
102
|
+
For maker funding, initialize the market Vault if needed, activate the Strand
|
|
103
|
+
or Current, then deposit with `strata_vault_deposit`. The market keeps that
|
|
104
|
+
available collateral while a control is live and returns it after the final
|
|
105
|
+
control is disabled, exhausted, expired, or cancelled. Current follows Strata's
|
|
106
|
+
live mark and needs no separate publisher transaction.
|
|
76
107
|
|
|
77
108
|
## Hosted Streamable HTTP
|
|
78
109
|
|
package/dist/src/server.js
CHANGED
|
@@ -6,6 +6,74 @@ import { STRATA_AGENT_HARNESS, STRATA_AGENT_HARNESS_INSTRUCTIONS, STRATA_AGENT_H
|
|
|
6
6
|
import { SERVER_VERSION } from "./version.js";
|
|
7
7
|
const REFRESH_INTERVAL_MS = 5_000;
|
|
8
8
|
export const STRATA_PLATFORM_GRAPH_URI = "strata://platform-graph/v2";
|
|
9
|
+
const LEGACY_TOOL_CAPABILITIES = {
|
|
10
|
+
strata_markets: { ids: ["markets.read"] },
|
|
11
|
+
strata_quote: { ids: ["quotes.read"] },
|
|
12
|
+
strata_exact_output_quote: { ids: ["quotes.read"] },
|
|
13
|
+
strata_execution_challenge: { ids: ["trade.prepare"] },
|
|
14
|
+
strata_execution_prepare: { ids: ["trade.prepare"] },
|
|
15
|
+
strata_execution_submit: { ids: ["trade.submit"] },
|
|
16
|
+
strata_order_challenge: { ids: ["orders.prepare"] },
|
|
17
|
+
strata_order_prepare: { ids: ["orders.prepare"] },
|
|
18
|
+
strata_order_submit: { ids: ["orders.submit"] },
|
|
19
|
+
strata_order_status: { ids: ["orders.submit"] },
|
|
20
|
+
strata_market_making_strand_prepare: { ids: ["mm.strand.manage"] },
|
|
21
|
+
strata_market_making_strand_submit: { ids: ["mm.strand.manage"] },
|
|
22
|
+
strata_market_making_current_prepare: { ids: ["mm.current.manage"] },
|
|
23
|
+
strata_market_making_current_submit: { ids: ["mm.current.manage"] },
|
|
24
|
+
strata_market_making_prepare: { ids: ["mm.strand.manage", "mm.current.manage"], match: "any" },
|
|
25
|
+
strata_market_making_submit_and_wait: { ids: ["mm.strand.manage", "mm.current.manage"], match: "any" },
|
|
26
|
+
strata_execute_quote: { ids: ["trade.submit"] },
|
|
27
|
+
strata_order_execute: { ids: ["orders.prepare", "orders.submit"] },
|
|
28
|
+
};
|
|
29
|
+
const PLATFORM_TOOL_CAPABILITIES = {
|
|
30
|
+
strata_status: { ids: ["platform.status.read"] },
|
|
31
|
+
strata_platform_graph: { ids: ["graphs.read"] },
|
|
32
|
+
strata_candles: { ids: ["market_data.candles.read"] },
|
|
33
|
+
strata_marks: { ids: ["market_data.marks.read"] },
|
|
34
|
+
strata_quote: { ids: ["quotes.market.read"] },
|
|
35
|
+
strata_swap_quote: { ids: ["quotes.swap.read"] },
|
|
36
|
+
strata_exact_output_quote: { ids: ["quotes.exact_output.read"] },
|
|
37
|
+
strata_execution_challenge: { ids: ["execution.prepare"] },
|
|
38
|
+
strata_execution_prepare: { ids: ["execution.prepare"] },
|
|
39
|
+
strata_execution_submit: { ids: ["execution.submit"] },
|
|
40
|
+
strata_execution_status: { ids: ["execution.status.read"] },
|
|
41
|
+
strata_order_challenge: { ids: ["orders.prepare"] },
|
|
42
|
+
strata_order_prepare: { ids: ["orders.prepare"] },
|
|
43
|
+
strata_order_submit: { ids: ["orders.submit"] },
|
|
44
|
+
strata_twap_challenge: { ids: ["algos.twap.place"] },
|
|
45
|
+
strata_twap_cancel: { ids: ["algos.twap.cancel"] },
|
|
46
|
+
strata_twap_prepare: { ids: ["algos.twap.place", "algos.twap.cancel"], match: "any" },
|
|
47
|
+
strata_twap_submit: { ids: ["algos.twap.place", "algos.twap.cancel"], match: "any" },
|
|
48
|
+
strata_twaps: { ids: ["algos.twap.read"] },
|
|
49
|
+
strata_portfolio: { ids: ["portfolio.read"] },
|
|
50
|
+
strata_portfolio_history: { ids: ["portfolio.history.read"] },
|
|
51
|
+
strata_vault_status: { ids: ["vault.status.read"] },
|
|
52
|
+
strata_vault_setup: { ids: ["vault.setup"] },
|
|
53
|
+
strata_vault_deposit: { ids: ["vault.deposit"] },
|
|
54
|
+
strata_vault_withdraw: { ids: ["vault.withdraw"] },
|
|
55
|
+
strata_vault_delegate: { ids: ["vault.delegate.manage"] },
|
|
56
|
+
strata_vault_policy: { ids: ["vault.policy.manage"] },
|
|
57
|
+
strata_vault_pause: { ids: ["vault.pause"] },
|
|
58
|
+
strata_vault_submit: { ids: ["vault.relay"] },
|
|
59
|
+
strata_vault_submission: { ids: ["vault.relay"] },
|
|
60
|
+
strata_market_making_status: { ids: ["mm.status.read"] },
|
|
61
|
+
strata_market_making_reputation: { ids: ["mm.reputation.read"] },
|
|
62
|
+
strata_market_making_strand_prepare: { ids: ["mm.strand.manage"] },
|
|
63
|
+
strata_market_making_strand_submit: { ids: ["mm.strand.manage"] },
|
|
64
|
+
strata_market_making_current_prepare: { ids: ["mm.current.manage"] },
|
|
65
|
+
strata_market_making_current_submit: { ids: ["mm.current.manage"] },
|
|
66
|
+
strata_market_making_prepare: { ids: ["mm.strand.manage", "mm.current.manage"], match: "any" },
|
|
67
|
+
strata_market_making_submit_and_wait: { ids: ["mm.strand.manage", "mm.current.manage"], match: "any" },
|
|
68
|
+
strata_rewards: { ids: ["rewards.read"] },
|
|
69
|
+
strata_referrals: { ids: ["referrals.read"] },
|
|
70
|
+
strata_referral_link: { ids: ["referrals.link"] },
|
|
71
|
+
strata_referral_claim: { ids: ["referrals.claim"] },
|
|
72
|
+
strata_bug_submit: { ids: ["bugs.submit"] },
|
|
73
|
+
strata_bugs: { ids: ["bugs.read"] },
|
|
74
|
+
strata_order_execute: { ids: ["orders.prepare", "orders.submit"] },
|
|
75
|
+
strata_twap_execute: { ids: ["algos.twap.place", "algos.twap.cancel"], match: "any" },
|
|
76
|
+
};
|
|
9
77
|
export function capabilityAvailable(catalog, id) {
|
|
10
78
|
return catalog.capabilities.some((capability) => capability.id === id
|
|
11
79
|
&& capability.default_enabled
|
|
@@ -184,12 +252,15 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
184
252
|
if (initialCatalog.contract_version !== STRATA_AGENT_HARNESS.contract_version) {
|
|
185
253
|
throw new Error("agent harness and live contract versions differ");
|
|
186
254
|
}
|
|
255
|
+
const initialPlatformCatalog = await platformClient.discovery.read();
|
|
187
256
|
const server = new McpServer({
|
|
188
257
|
name: "strata",
|
|
189
258
|
version: SERVER_VERSION,
|
|
190
259
|
}, {
|
|
191
260
|
instructions: STRATA_AGENT_HARNESS_INSTRUCTIONS,
|
|
192
261
|
});
|
|
262
|
+
const { registerTool, handles: registeredTools } = trackedToolRegistrar(server);
|
|
263
|
+
const makerQuickstartPreparations = new Map();
|
|
193
264
|
server.registerResource("strata_agent_harness", STRATA_AGENT_HARNESS_URI, {
|
|
194
265
|
title: "Strata Agent Harness",
|
|
195
266
|
description: "Canonical capability-gated first-run workflow for Strata agents.",
|
|
@@ -251,7 +322,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
251
322
|
},
|
|
252
323
|
],
|
|
253
324
|
}));
|
|
254
|
-
|
|
325
|
+
registerTool("strata_capabilities", {
|
|
255
326
|
title: "Strata capabilities",
|
|
256
327
|
description: "See which Strata features are currently available to MCP clients.",
|
|
257
328
|
annotations: {
|
|
@@ -261,7 +332,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
261
332
|
openWorldHint: true,
|
|
262
333
|
},
|
|
263
334
|
}, async () => toolResult(await client.capabilities(), "Current Strata capabilities."));
|
|
264
|
-
|
|
335
|
+
registerTool("strata_action_graph", {
|
|
265
336
|
title: "Strata action graph",
|
|
266
337
|
description: "Discover live operations, required capabilities, transition conditions, and external signing boundaries.",
|
|
267
338
|
annotations: {
|
|
@@ -271,7 +342,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
271
342
|
openWorldHint: true,
|
|
272
343
|
},
|
|
273
344
|
}, async () => toolResult(await client.actionGraph(), "Current Strata action graph."));
|
|
274
|
-
|
|
345
|
+
registerTool("strata_platform_graph", {
|
|
275
346
|
title: "Strata platform graph",
|
|
276
347
|
description: "Discover every public module, entity relationship, operation binding, workflow, and live availability gate.",
|
|
277
348
|
annotations: {
|
|
@@ -285,7 +356,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
285
356
|
const liveOperations = graph.operations.filter((operation) => operation.available).length;
|
|
286
357
|
return toolResult(graph, `${liveOperations} of ${graph.operations.length} mapped Strata operations are currently live.`);
|
|
287
358
|
});
|
|
288
|
-
|
|
359
|
+
registerTool("strata_market_making_status", {
|
|
289
360
|
title: "Read Strata maker status",
|
|
290
361
|
description: "A maker's products, live exposure, health, and kill state in one market — public by wallet address, no signature.",
|
|
291
362
|
inputSchema: {
|
|
@@ -302,7 +373,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
302
373
|
const response = await platformClient.marketMaking.status(marketId, walletAddress);
|
|
303
374
|
return toolResult(response, `${response.active_products} active maker products; reconcile intent, Strand, Current, signed-quote, and dead-man state before changing exposure.`);
|
|
304
375
|
});
|
|
305
|
-
|
|
376
|
+
registerTool("strata_market_making_reputation", {
|
|
306
377
|
title: "Read Strata maker reputation",
|
|
307
378
|
description: "A maker's reliability, participation, tier, and signed-quote eligibility in one market — public by wallet address, no signature.",
|
|
308
379
|
inputSchema: {
|
|
@@ -316,7 +387,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
316
387
|
openWorldHint: true,
|
|
317
388
|
},
|
|
318
389
|
}, async ({ marketId, walletAddress }) => toolResult(await platformClient.marketMaking.reputation(marketId, walletAddress), "Maker reputation record. Use tier_progress and signed_quote_stream_eligible before choosing a maker transport."));
|
|
319
|
-
|
|
390
|
+
registerTool("strata_status", {
|
|
320
391
|
title: "Strata status",
|
|
321
392
|
description: "Read product-level readiness and the number of currently live mapped operations.",
|
|
322
393
|
annotations: {
|
|
@@ -329,7 +400,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
329
400
|
const status = await platformClient.discovery.status();
|
|
330
401
|
return toolResult(status, `Strata is ${status.status}; ${status.available_operations} mapped operations are live.`);
|
|
331
402
|
});
|
|
332
|
-
|
|
403
|
+
registerTool("strata_candles", {
|
|
333
404
|
title: "Strata candles",
|
|
334
405
|
description: "Read bounded time-bucketed candles for one opaque Strata market ID.",
|
|
335
406
|
inputSchema: {
|
|
@@ -352,7 +423,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
352
423
|
});
|
|
353
424
|
return toolResult(candles, `${candles.candles.length} Strata candles returned.`);
|
|
354
425
|
});
|
|
355
|
-
|
|
426
|
+
registerTool("strata_marks", {
|
|
356
427
|
title: "Strata mark",
|
|
357
428
|
description: "Read the current customer-facing reference price for one opaque market ID.",
|
|
358
429
|
inputSchema: {
|
|
@@ -368,7 +439,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
368
439
|
const mark = await platformClient.marketData.mark(marketId);
|
|
369
440
|
return toolResult(mark, mark.stale ? "Strata mark is stale." : "Current Strata mark.");
|
|
370
441
|
});
|
|
371
|
-
|
|
442
|
+
registerTool("strata_book", {
|
|
372
443
|
title: "Strata order book",
|
|
373
444
|
description: "Read the executable order book for one opaque market ID: bids and asks, one size per price "
|
|
374
445
|
+ "level. Top of book is the best bid and ask.",
|
|
@@ -392,7 +463,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
392
463
|
const book = await platformClient.books.snapshot(marketId, depth === undefined ? {} : { depth });
|
|
393
464
|
return toolResult(book, `Book for ${marketId}: ${book.bids.length} bid / ${book.asks.length} ask levels at sequence ${book.sequence}.`);
|
|
394
465
|
});
|
|
395
|
-
|
|
466
|
+
registerTool("strata_bbo", {
|
|
396
467
|
title: "Strata best bid/ask",
|
|
397
468
|
description: "Read the current best bid and best ask (top of book) for one opaque market ID.",
|
|
398
469
|
inputSchema: {
|
|
@@ -408,7 +479,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
408
479
|
const bbo = await platformClient.books.bestBidAsk(marketId);
|
|
409
480
|
return toolResult(bbo, `BBO for ${marketId}: bid ${bbo.best_bid?.price_atoms ?? "—"} / ask ${bbo.best_ask?.price_atoms ?? "—"}.`);
|
|
410
481
|
});
|
|
411
|
-
|
|
482
|
+
registerTool("strata_trades", {
|
|
412
483
|
title: "Strata recent trades",
|
|
413
484
|
description: "Read recent anonymized prints for one opaque market ID: price, size, side, and time.",
|
|
414
485
|
inputSchema: {
|
|
@@ -431,7 +502,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
431
502
|
const trades = await platformClient.books.trades(marketId, limit === undefined ? {} : { limit });
|
|
432
503
|
return toolResult(trades, `${trades.trades.length} recent prints for ${marketId}.`);
|
|
433
504
|
});
|
|
434
|
-
|
|
505
|
+
registerTool("strata_execution_status", {
|
|
435
506
|
title: "Strata execution status",
|
|
436
507
|
description: "Recover prepared state or a restart-durable confirmed execution receipt.",
|
|
437
508
|
inputSchema: {
|
|
@@ -448,7 +519,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
448
519
|
const receipt = await platformClient.executions.status(marketId, executionId);
|
|
449
520
|
return toolResult(receipt, `Execution is ${receipt.status}.`);
|
|
450
521
|
});
|
|
451
|
-
|
|
522
|
+
registerTool("strata_twaps", {
|
|
452
523
|
title: "Strata TWAPs",
|
|
453
524
|
description: "Read sanitized progress and terminal receipts for wallet-owned TWAP schedules.",
|
|
454
525
|
inputSchema: {
|
|
@@ -465,7 +536,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
465
536
|
const response = await platformClient.algos.twaps(marketId, walletAddress);
|
|
466
537
|
return toolResult(response, `${response.twaps.length} TWAP schedules returned.`);
|
|
467
538
|
});
|
|
468
|
-
|
|
539
|
+
registerTool("strata_twap_challenge", {
|
|
469
540
|
title: "Prepare a Strata TWAP authorization",
|
|
470
541
|
description: "Request exact external-signing bytes for a bounded TWAP schedule.",
|
|
471
542
|
inputSchema: {
|
|
@@ -499,7 +570,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
499
570
|
});
|
|
500
571
|
return toolResult(response, "Sign the returned authorization payload externally.");
|
|
501
572
|
});
|
|
502
|
-
|
|
573
|
+
registerTool("strata_twap_cancel", {
|
|
503
574
|
title: "Prepare Strata TWAP cancellation",
|
|
504
575
|
description: "Request exact external-signing bytes to cancel one active owned TWAP.",
|
|
505
576
|
inputSchema: {
|
|
@@ -523,7 +594,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
523
594
|
});
|
|
524
595
|
return toolResult(response, "Sign the returned cancellation payload externally.");
|
|
525
596
|
});
|
|
526
|
-
|
|
597
|
+
registerTool("strata_twap_prepare", {
|
|
527
598
|
title: "Prepare Strata TWAP transaction",
|
|
528
599
|
description: "Prepare a canonical TWAP transaction. One signature: pass the action itself (place fields or twapId to cancel) and sign only the returned transaction. (A challengeId + authorizationSignature is still accepted.)",
|
|
529
600
|
inputSchema: {
|
|
@@ -596,7 +667,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
596
667
|
const response = await platformClient.algos.prepare(input.marketId, { operation });
|
|
597
668
|
return toolResult(response, "One signature: verify this canonical transaction, then sign it externally with the session key and submit.");
|
|
598
669
|
});
|
|
599
|
-
|
|
670
|
+
registerTool("strata_twap_submit", {
|
|
600
671
|
title: "Submit Strata TWAP transaction",
|
|
601
672
|
description: "Submit the exact externally signed TWAP transaction idempotently.",
|
|
602
673
|
inputSchema: {
|
|
@@ -619,7 +690,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
619
690
|
});
|
|
620
691
|
return toolResult(response, `TWAP action submitted as ${response.signature}.`);
|
|
621
692
|
});
|
|
622
|
-
|
|
693
|
+
registerTool("strata_portfolio", {
|
|
623
694
|
title: "Strata account",
|
|
624
695
|
description: "The whole account in one public read, by wallet address: balances (total / available / locked, exact USD), positions, open orders, and recent fills across every live market. No signature, no session key, no market selection.",
|
|
625
696
|
inputSchema: {
|
|
@@ -641,7 +712,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
641
712
|
? `${response.balances.length} held assets; ${activity}; equity ${response.equity_usd_micros} USD micros at slot ${response.observed_slot}.`
|
|
642
713
|
: `${response.balances.length} held assets; ${activity}; ${response.unpriced_asset_ids.length} unpriced, USD totals unavailable.`);
|
|
643
714
|
});
|
|
644
|
-
|
|
715
|
+
registerTool("strata_portfolio_history", {
|
|
645
716
|
title: "Strata portfolio history",
|
|
646
717
|
description: "Read genuine stored account-equity history in exact USD micros.",
|
|
647
718
|
inputSchema: {
|
|
@@ -658,7 +729,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
658
729
|
const response = await platformClient.account.portfolioHistory(walletAddress, range);
|
|
659
730
|
return toolResult(response, `${response.points.length} stored equity samples returned.`);
|
|
660
731
|
});
|
|
661
|
-
|
|
732
|
+
registerTool("strata_vault_status", {
|
|
662
733
|
title: "Strata Vault status",
|
|
663
734
|
description: "Read sealed owner state and optional external-session readiness without construction identifiers.",
|
|
664
735
|
inputSchema: {
|
|
@@ -677,7 +748,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
677
748
|
? `Vault is ${response.state}; no session was requested.`
|
|
678
749
|
: `Vault is ${response.state}; requested session is ${response.session.state}.`);
|
|
679
750
|
});
|
|
680
|
-
|
|
751
|
+
registerTool("strata_vault_pause", {
|
|
681
752
|
title: "Prepare Strata Vault pause",
|
|
682
753
|
description: "Prepare an owner-authorized pause or resume transaction for external verification, signing, and broadcast.",
|
|
683
754
|
inputSchema: {
|
|
@@ -694,7 +765,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
694
765
|
const response = await platformClient.vault.preparePause({ walletAddress, paused });
|
|
695
766
|
return toolResult(response, `Verify this ${paused ? "pause" : "resume"} transaction, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).`);
|
|
696
767
|
});
|
|
697
|
-
|
|
768
|
+
registerTool("strata_vault_setup", {
|
|
698
769
|
title: "Prepare Strata Vault onboarding",
|
|
699
770
|
description: "One-signature onboarding: register an external session key for a wallet. Only the wallet and the session key are needed; one session then trades every market. Policy fields are optional. A first strata_vault_deposit that names the session key does this in the same transaction.",
|
|
700
771
|
inputSchema: {
|
|
@@ -733,7 +804,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
733
804
|
});
|
|
734
805
|
return toolResult(response, "Verify every echoed session policy field, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).");
|
|
735
806
|
});
|
|
736
|
-
|
|
807
|
+
registerTool("strata_vault_deposit", {
|
|
737
808
|
title: "Prepare Strata Vault deposit",
|
|
738
809
|
description: "Prepare an exact owner-funded Vault deposit using opaque market and asset IDs. Name sessionPublicKey and a first deposit also registers that session in the same transaction (one owner signature onboards and funds the wallet).",
|
|
739
810
|
inputSchema: {
|
|
@@ -761,7 +832,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
761
832
|
? "This deposit also registers the session key. Verify the exact market, asset, amount, and session, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true)."
|
|
762
833
|
: "Verify the exact market, asset, and amount, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).");
|
|
763
834
|
});
|
|
764
|
-
|
|
835
|
+
registerTool("strata_vault_withdraw", {
|
|
765
836
|
title: "Prepare Strata Vault withdrawal",
|
|
766
837
|
description: "Prepare an exact owner-authorized withdrawal to a destination wallet.",
|
|
767
838
|
inputSchema: {
|
|
@@ -787,7 +858,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
787
858
|
});
|
|
788
859
|
return toolResult(response, "Verify the exact destination and amount, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).");
|
|
789
860
|
});
|
|
790
|
-
|
|
861
|
+
registerTool("strata_vault_delegate", {
|
|
791
862
|
title: "Prepare Strata Vault session control",
|
|
792
863
|
description: "Prepare owner-authorized revocation of one externally held Vault session key.",
|
|
793
864
|
inputSchema: {
|
|
@@ -809,7 +880,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
809
880
|
});
|
|
810
881
|
return toolResult(response, "Verify both identities and the destructive action, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).");
|
|
811
882
|
});
|
|
812
|
-
|
|
883
|
+
registerTool("strata_vault_policy", {
|
|
813
884
|
title: "Prepare Strata Vault withdrawal policy",
|
|
814
885
|
description: "Prepare an owner-authorized blocked or restricted withdrawal access policy.",
|
|
815
886
|
inputSchema: {
|
|
@@ -830,7 +901,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
830
901
|
});
|
|
831
902
|
return toolResult(response, "Verify the exact withdrawal access policy, then owner-sign it and pass preparation_id + the signed transaction to strata_vault_submit (Strata pays the fee when sponsored is true).");
|
|
832
903
|
});
|
|
833
|
-
|
|
904
|
+
registerTool("strata_vault_submit", {
|
|
834
905
|
title: "Submit a prepared Strata Vault transaction",
|
|
835
906
|
description: "Submit an owner-signed prepared Vault transaction (setup, deposit, withdrawal, session, "
|
|
836
907
|
+ "policy, pause). Strata verifies it is exactly the prepared transaction, pays the network "
|
|
@@ -857,7 +928,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
857
928
|
return toolResult(response, `Vault ${response.action} ${response.status}${response.sponsored ? " (Strata paid the fee)" : ""}: `
|
|
858
929
|
+ `signature ${response.signature}. Poll strata_vault_submission until confirmed.`);
|
|
859
930
|
});
|
|
860
|
-
|
|
931
|
+
registerTool("strata_vault_submission", {
|
|
861
932
|
title: "Strata Vault submission status",
|
|
862
933
|
description: "Read the durable outcome of a submitted Vault transaction: submitted, confirmed, or failed.",
|
|
863
934
|
inputSchema: {
|
|
@@ -874,7 +945,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
874
945
|
return toolResult(response, `Vault ${response.action} is ${response.status}`
|
|
875
946
|
+ `${response.failure_code ? ` (${response.failure_code})` : ""}.`);
|
|
876
947
|
});
|
|
877
|
-
|
|
948
|
+
registerTool("strata_rewards", {
|
|
878
949
|
title: "Strata rewards",
|
|
879
950
|
description: "Read the current rewards season, standings, and optional owner score.",
|
|
880
951
|
inputSchema: {
|
|
@@ -891,7 +962,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
891
962
|
const response = await platformClient.rewards.read({ walletAddress, limit });
|
|
892
963
|
return toolResult(response, `${response.standings.length} reward standings returned.`);
|
|
893
964
|
});
|
|
894
|
-
|
|
965
|
+
registerTool("strata_referrals", {
|
|
895
966
|
title: "Strata referrals",
|
|
896
967
|
description: "Read an owner's referral state and exact claimable reward atoms.",
|
|
897
968
|
inputSchema: {
|
|
@@ -907,7 +978,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
907
978
|
const response = await platformClient.referrals.read(walletAddress);
|
|
908
979
|
return toolResult(response, response.enabled ? "Referral state returned." : "Referrals are disabled.");
|
|
909
980
|
});
|
|
910
|
-
|
|
981
|
+
registerTool("strata_referral_link", {
|
|
911
982
|
title: "Link a Strata referral",
|
|
912
983
|
description: "Prepare or submit an externally authorized referral link for a new wallet.",
|
|
913
984
|
inputSchema: {
|
|
@@ -936,7 +1007,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
936
1007
|
});
|
|
937
1008
|
return toolResult(response, "Referral link is pending the wallet's first fill.");
|
|
938
1009
|
});
|
|
939
|
-
|
|
1010
|
+
registerTool("strata_referral_claim", {
|
|
940
1011
|
title: "Claim Strata referral rewards",
|
|
941
1012
|
description: "Prepare or submit an externally authorized request for currently claimable referral rewards.",
|
|
942
1013
|
inputSchema: {
|
|
@@ -967,7 +1038,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
967
1038
|
});
|
|
968
1039
|
return toolResult(response, `${response.claimable_atoms} referral reward atoms requested.`);
|
|
969
1040
|
});
|
|
970
|
-
|
|
1041
|
+
registerTool("strata_bugs", {
|
|
971
1042
|
title: "Strata bug reports",
|
|
972
1043
|
description: "Read an owner's redacted bug reports and confirmed points.",
|
|
973
1044
|
inputSchema: {
|
|
@@ -983,7 +1054,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
983
1054
|
const response = await platformClient.bugs.read(walletAddress);
|
|
984
1055
|
return toolResult(response, `${response.reports.length} redacted bug reports returned.`);
|
|
985
1056
|
});
|
|
986
|
-
|
|
1057
|
+
registerTool("strata_bug_submit", {
|
|
987
1058
|
title: "Submit Strata bug report",
|
|
988
1059
|
description: "Prepare or submit a bug report. Omit authorizationSignature to receive the exact "
|
|
989
1060
|
+ "payload for the owner wallet to sign externally; provide that hex signature to submit.",
|
|
@@ -1013,7 +1084,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1013
1084
|
});
|
|
1014
1085
|
return toolResult(response, `Bug report ${response.bug_id} is pending review.`);
|
|
1015
1086
|
});
|
|
1016
|
-
const markets =
|
|
1087
|
+
const markets = registerTool("strata_markets", {
|
|
1017
1088
|
title: "Strata markets",
|
|
1018
1089
|
description: "List Strata markets and their current Sonar quote availability.",
|
|
1019
1090
|
inputSchema: {
|
|
@@ -1048,7 +1119,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1048
1119
|
? `; ${identified} carry a market_id — pass it as marketId to every by-market tool.`
|
|
1049
1120
|
: "."));
|
|
1050
1121
|
}));
|
|
1051
|
-
const quote =
|
|
1122
|
+
const quote = registerTool("strata_quote", {
|
|
1052
1123
|
title: "Sonar quote",
|
|
1053
1124
|
description: "Request a short-lived Sonar quote for a Strata market. Returns expected "
|
|
1054
1125
|
+ "output, minimum output, fees, price impact, and expiry.",
|
|
@@ -1091,7 +1162,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1091
1162
|
const response = await client.quote(request);
|
|
1092
1163
|
return toolResult(response, quoteSummary(response));
|
|
1093
1164
|
}));
|
|
1094
|
-
const exactOutputQuote =
|
|
1165
|
+
const exactOutputQuote = registerTool("strata_exact_output_quote", {
|
|
1095
1166
|
title: "Sonar exact-output quote",
|
|
1096
1167
|
description: "Request a short-lived Sonar quote for an exact output amount (for example: buy "
|
|
1097
1168
|
+ "1 SOL). Strata inverts its best route and returns the input that delivers it as "
|
|
@@ -1138,7 +1209,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1138
1209
|
const response = await client.quote(request);
|
|
1139
1210
|
return toolResult(response, quoteSummary(response));
|
|
1140
1211
|
}));
|
|
1141
|
-
|
|
1212
|
+
registerTool("strata_swap_quote", {
|
|
1142
1213
|
title: "Sonar asset swap quote",
|
|
1143
1214
|
description: "Request short-lived exact-input customer economics between two opaque Strata asset IDs.",
|
|
1144
1215
|
inputSchema: {
|
|
@@ -1164,7 +1235,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1164
1235
|
+ `${response.amount_out_atoms} user-net output atoms; minimum `
|
|
1165
1236
|
+ `${response.minimum_output_atoms}; expires at ${response.expires_at_ms}.`);
|
|
1166
1237
|
});
|
|
1167
|
-
const executionChallenge =
|
|
1238
|
+
const executionChallenge = registerTool("strata_execution_challenge", {
|
|
1168
1239
|
title: "Strata execution challenge",
|
|
1169
1240
|
description: "Request canonical quote-bound authorization bytes for the external signer configured by the agent owner.",
|
|
1170
1241
|
inputSchema: {
|
|
@@ -1200,7 +1271,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1200
1271
|
const response = await client.executionChallenge(request);
|
|
1201
1272
|
return toolResult(response, `Authorization challenge ${response.challenge_id}; expires at ${response.expires_at_ms}.`);
|
|
1202
1273
|
}));
|
|
1203
|
-
const executionPrepare =
|
|
1274
|
+
const executionPrepare = registerTool("strata_execution_prepare", {
|
|
1204
1275
|
title: "Prepare Strata execution",
|
|
1205
1276
|
description: "Prepare a quote-bound partially signed transaction. One signature: pass quoteId + ownerWallet + sessionPublicKey and sign only the returned transaction. (A challengeId + authorizationSignature from strata_execution_challenge is still accepted.)",
|
|
1206
1277
|
inputSchema: {
|
|
@@ -1251,7 +1322,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1251
1322
|
const response = await client.executionPrepare(request);
|
|
1252
1323
|
return toolResult(response, `Prepared execution ${response.execution_id}; verify it, then sign the transaction externally with the session key before ${response.expires_at_ms} and submit.`);
|
|
1253
1324
|
}));
|
|
1254
|
-
const executionSubmit =
|
|
1325
|
+
const executionSubmit = registerTool("strata_execution_submit", {
|
|
1255
1326
|
title: "Submit Strata execution",
|
|
1256
1327
|
description: "Submit an externally signed prepared transaction with an idempotency key.",
|
|
1257
1328
|
inputSchema: {
|
|
@@ -1289,7 +1360,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1289
1360
|
const response = await client.executionSubmit(request);
|
|
1290
1361
|
return toolResult(response, `Submitted execution ${response.execution_id} as ${response.signature}.`);
|
|
1291
1362
|
}));
|
|
1292
|
-
const orderChallenge =
|
|
1363
|
+
const orderChallenge = registerTool("strata_order_challenge", {
|
|
1293
1364
|
title: "Strata order challenge",
|
|
1294
1365
|
description: "Bind an atomic place, cancel, cancel-all, replace, or bounded batch request to canonical bytes for the agent owner's external signer.",
|
|
1295
1366
|
inputSchema: {
|
|
@@ -1334,7 +1405,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1334
1405
|
const response = await platformClient.orders.challenge(args.marketId, request);
|
|
1335
1406
|
return toolResult(response, `Order challenge ${response.challenge_id} binds ${response.order_ids.length} opaque order ID(s); expires at ${response.expires_at_ms}.`);
|
|
1336
1407
|
}));
|
|
1337
|
-
const orderPrepare =
|
|
1408
|
+
const orderPrepare = registerTool("strata_order_prepare", {
|
|
1338
1409
|
title: "Prepare Strata order control",
|
|
1339
1410
|
description: "Prepare an immutable partially signed order-control transaction. One signature: pass the operation itself (same fields as strata_order_challenge) and sign only the returned transaction with the session key. (A challengeId + authorizationSignature from strata_order_challenge is still accepted.)",
|
|
1340
1411
|
inputSchema: {
|
|
@@ -1398,7 +1469,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1398
1469
|
const response = await platformClient.orders.prepare(args.marketId, { operation: mapped });
|
|
1399
1470
|
return toolResult(response, `Prepared ${response.action} control ${response.order_control_id} — one signature: verify it, sign the transaction externally with the session key before ${response.expires_at_ms}, then submit.`);
|
|
1400
1471
|
}));
|
|
1401
|
-
const orderSubmit =
|
|
1472
|
+
const orderSubmit = registerTool("strata_order_submit", {
|
|
1402
1473
|
title: "Submit Strata order control",
|
|
1403
1474
|
description: "Submit an externally signed order transaction with a stable retry key.",
|
|
1404
1475
|
inputSchema: {
|
|
@@ -1425,7 +1496,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1425
1496
|
});
|
|
1426
1497
|
return toolResult(response, `Submitted ${response.action} control ${response.order_control_id} as ${response.signature}.`);
|
|
1427
1498
|
}));
|
|
1428
|
-
const orderStatus =
|
|
1499
|
+
const orderStatus = registerTool("strata_order_status", {
|
|
1429
1500
|
title: "Read Strata order-control status",
|
|
1430
1501
|
description: "Recover the durable result for an externally signed order submission after a timeout or restart.",
|
|
1431
1502
|
inputSchema: {
|
|
@@ -1443,7 +1514,110 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1443
1514
|
const response = await platformClient.orders.status(marketId, { orderControlId, idempotencyKey });
|
|
1444
1515
|
return toolResult(response, `Order control ${response.order_control_id} is ${response.status}.`);
|
|
1445
1516
|
}));
|
|
1446
|
-
const
|
|
1517
|
+
const makerPrepare = registerTool("strata_market_making_prepare", {
|
|
1518
|
+
title: "Prepare simple Strata market making",
|
|
1519
|
+
description: "Prepare a pro-level Strand or Current from a market label, decimal base size, spread, and duration. Strata resolves IDs, decimals, live mark, tick grid, expiry, safety bounds, and fixed on-chain arrays. Sign only the returned transaction externally, then call submit_and_wait.",
|
|
1520
|
+
inputSchema: {
|
|
1521
|
+
action: z.enum(["start", "stop"]),
|
|
1522
|
+
market: z.string().min(1).max(128),
|
|
1523
|
+
product: z.enum(["strand", "current"]),
|
|
1524
|
+
makerWallet: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/),
|
|
1525
|
+
spreadBps: z.number().int().min(1).max(5_000).optional(),
|
|
1526
|
+
size: z.string().min(1).max(64).optional(),
|
|
1527
|
+
duration: z.union([
|
|
1528
|
+
z.number().int().min(1).max(604_800),
|
|
1529
|
+
z.string().regex(/^[1-9][0-9]*(?:s|m|h|d)$/i),
|
|
1530
|
+
]).optional(),
|
|
1531
|
+
levels: z.number().int().min(1).max(16).optional(),
|
|
1532
|
+
levelStepBps: z.number().int().min(1).max(5_000).optional(),
|
|
1533
|
+
side: z.enum(["both", "buy", "sell"]).optional(),
|
|
1534
|
+
asyncOnly: z.boolean().optional(),
|
|
1535
|
+
},
|
|
1536
|
+
annotations: {
|
|
1537
|
+
readOnlyHint: false,
|
|
1538
|
+
destructiveHint: true,
|
|
1539
|
+
idempotentHint: false,
|
|
1540
|
+
openWorldHint: true,
|
|
1541
|
+
},
|
|
1542
|
+
}, async (args) => guardedTool(client, `mm.${args.product}.manage`, async () => {
|
|
1543
|
+
const prepared = args.action === "stop"
|
|
1544
|
+
? await platformClient.marketMaking.prepareStop({
|
|
1545
|
+
market: args.market,
|
|
1546
|
+
product: args.product,
|
|
1547
|
+
makerWallet: args.makerWallet,
|
|
1548
|
+
})
|
|
1549
|
+
: (() => {
|
|
1550
|
+
if (args.spreadBps === undefined || args.size === undefined) {
|
|
1551
|
+
return undefined;
|
|
1552
|
+
}
|
|
1553
|
+
return platformClient.marketMaking.prepareStart({
|
|
1554
|
+
market: args.market,
|
|
1555
|
+
product: args.product,
|
|
1556
|
+
makerWallet: args.makerWallet,
|
|
1557
|
+
spreadBps: args.spreadBps,
|
|
1558
|
+
size: args.size,
|
|
1559
|
+
...(args.duration === undefined ? {} : { duration: args.duration }),
|
|
1560
|
+
...(args.levels === undefined ? {} : { levels: args.levels }),
|
|
1561
|
+
...(args.levelStepBps === undefined ? {} : { levelStepBps: args.levelStepBps }),
|
|
1562
|
+
...(args.side === undefined ? {} : { side: args.side }),
|
|
1563
|
+
...(args.asyncOnly === undefined ? {} : { asyncOnly: args.asyncOnly }),
|
|
1564
|
+
});
|
|
1565
|
+
})();
|
|
1566
|
+
if (prepared === undefined) {
|
|
1567
|
+
return toolError("invalid_request", "Starting market making requires spreadBps and size.", false);
|
|
1568
|
+
}
|
|
1569
|
+
const resolved = await prepared;
|
|
1570
|
+
makerQuickstartPreparations.set(resolved.prepared.maker_control_id, resolved);
|
|
1571
|
+
while (makerQuickstartPreparations.size > 128) {
|
|
1572
|
+
const oldest = makerQuickstartPreparations.keys().next().value;
|
|
1573
|
+
if (oldest === undefined)
|
|
1574
|
+
break;
|
|
1575
|
+
makerQuickstartPreparations.delete(oldest);
|
|
1576
|
+
}
|
|
1577
|
+
const response = {
|
|
1578
|
+
action: args.action,
|
|
1579
|
+
market: resolved.market,
|
|
1580
|
+
product: resolved.product,
|
|
1581
|
+
...("base_asset" in resolved ? { base_asset: resolved.base_asset } : {}),
|
|
1582
|
+
operation: resolved.operation,
|
|
1583
|
+
prepared: resolved.prepared,
|
|
1584
|
+
};
|
|
1585
|
+
return toolResult(response, `Prepared ${args.action} for ${resolved.market.label} as ${resolved.prepared.maker_control_id}. Verify and sign only prepared.transaction_base64, then submit it within 30 seconds.`);
|
|
1586
|
+
}));
|
|
1587
|
+
const makerSubmitAndWait = registerTool("strata_market_making_submit_and_wait", {
|
|
1588
|
+
title: "Submit and confirm Strata market making",
|
|
1589
|
+
description: "Submit the exact externally signed quickstart transaction and wait until Strata's chain-derived maker state confirms the product started or stopped. The control ID is its default idempotency key.",
|
|
1590
|
+
inputSchema: {
|
|
1591
|
+
makerControlId: z.string().regex(/^mc_[0-9a-f]{32}$/),
|
|
1592
|
+
signedTransactionBase64: z.string().min(4).max(4_096).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
|
|
1593
|
+
idempotencyKey: z.string().min(1).max(64).regex(/^[A-Za-z0-9._-]+$/).optional(),
|
|
1594
|
+
confirmationTimeoutMs: z.number().int().min(1_000).max(120_000).optional(),
|
|
1595
|
+
},
|
|
1596
|
+
annotations: {
|
|
1597
|
+
readOnlyHint: false,
|
|
1598
|
+
destructiveHint: true,
|
|
1599
|
+
idempotentHint: true,
|
|
1600
|
+
openWorldHint: true,
|
|
1601
|
+
},
|
|
1602
|
+
}, async (args) => {
|
|
1603
|
+
const prepared = makerQuickstartPreparations.get(args.makerControlId);
|
|
1604
|
+
if (!prepared) {
|
|
1605
|
+
return toolError("session_expired", "This quickstart preparation is not in the current MCP session. Prepare it again; maker transactions expire after 30 seconds.", false);
|
|
1606
|
+
}
|
|
1607
|
+
return guardedTool(client, `mm.${prepared.product}.manage`, async () => {
|
|
1608
|
+
const response = await platformClient.marketMaking.submitPrepared({
|
|
1609
|
+
prepared,
|
|
1610
|
+
signedTransactionBase64: args.signedTransactionBase64,
|
|
1611
|
+
...(args.idempotencyKey === undefined ? {} : { idempotencyKey: args.idempotencyKey }),
|
|
1612
|
+
...(args.confirmationTimeoutMs === undefined
|
|
1613
|
+
? {}
|
|
1614
|
+
: { confirmationTimeoutMs: args.confirmationTimeoutMs }),
|
|
1615
|
+
});
|
|
1616
|
+
makerQuickstartPreparations.delete(args.makerControlId);
|
|
1617
|
+
return toolResult(response, `${response.product} is confirmed ${response.operation.action === "cancel" ? "stopped" : "live"} on ${response.market.label}.`);
|
|
1618
|
+
});
|
|
1619
|
+
});
|
|
1620
|
+
const makerStrandPrepare = registerTool("strata_market_making_strand_prepare", {
|
|
1447
1621
|
title: "Prepare Strata Strand control",
|
|
1448
1622
|
description: "Build one exact unsigned maker-owned Strand transaction. Every exposure and level size is expressed in base-asset atoms, never lots or whole tokens. Verify and sign it externally with the maker wallet, then submit it with the Strand submit tool.",
|
|
1449
1623
|
inputSchema: {
|
|
@@ -1516,7 +1690,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1516
1690
|
const response = await platformClient.marketMaking.strand.prepare(args.marketId, request);
|
|
1517
1691
|
return toolResult(response, `Prepared ${response.action} control ${response.maker_control_id}; verify and sign only this transaction with ${response.maker_wallet} before ${response.expires_at_ms}.`);
|
|
1518
1692
|
}));
|
|
1519
|
-
const makerStrandSubmit =
|
|
1693
|
+
const makerStrandSubmit = registerTool("strata_market_making_strand_submit", {
|
|
1520
1694
|
title: "Submit Strata Strand control",
|
|
1521
1695
|
description: "Submit the exact externally maker-signed Strand transaction with a stable retry key.",
|
|
1522
1696
|
inputSchema: {
|
|
@@ -1539,9 +1713,9 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1539
1713
|
});
|
|
1540
1714
|
return toolResult(response, `Submitted ${response.action} as ${response.signature}.`);
|
|
1541
1715
|
}));
|
|
1542
|
-
const makerCurrentPrepare =
|
|
1716
|
+
const makerCurrentPrepare = registerTool("strata_market_making_current_prepare", {
|
|
1543
1717
|
title: "Prepare Strata Current control",
|
|
1544
|
-
description: "Build one exact unsigned maker-owned Current transaction. Upsert
|
|
1718
|
+
description: "Build one exact unsigned maker-owned Current transaction. Upsert prices its bands from the market's live Strata mark; cancel remains available independently.",
|
|
1545
1719
|
inputSchema: {
|
|
1546
1720
|
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
1547
1721
|
action: z.enum(["upsert", "cancel"]),
|
|
@@ -1599,7 +1773,7 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1599
1773
|
const response = await platformClient.marketMaking.current.prepare(args.marketId, request);
|
|
1600
1774
|
return toolResult(response, `Prepared ${response.action} control ${response.maker_control_id}; verify and sign only this transaction with ${response.maker_wallet} before ${response.expires_at_ms}.`);
|
|
1601
1775
|
}));
|
|
1602
|
-
const makerCurrentSubmit =
|
|
1776
|
+
const makerCurrentSubmit = registerTool("strata_market_making_current_submit", {
|
|
1603
1777
|
title: "Submit Strata Current control",
|
|
1604
1778
|
description: "Submit the exact externally maker-signed Current transaction with a stable retry key.",
|
|
1605
1779
|
inputSchema: {
|
|
@@ -1622,8 +1796,8 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1622
1796
|
});
|
|
1623
1797
|
return toolResult(response, `Submitted ${response.action} as ${response.signature}.`);
|
|
1624
1798
|
}));
|
|
1625
|
-
registerAutonomyTools(
|
|
1626
|
-
|
|
1799
|
+
registerAutonomyTools(registerTool, client, platformClient, options.sessionAutonomy, () => typeof Date !== "undefined" ? Date.now() : 0);
|
|
1800
|
+
void [
|
|
1627
1801
|
markets,
|
|
1628
1802
|
quote,
|
|
1629
1803
|
exactOutputQuote,
|
|
@@ -1634,17 +1808,23 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1634
1808
|
orderPrepare,
|
|
1635
1809
|
orderSubmit,
|
|
1636
1810
|
orderStatus,
|
|
1811
|
+
makerPrepare,
|
|
1812
|
+
makerSubmitAndWait,
|
|
1637
1813
|
makerStrandPrepare,
|
|
1638
1814
|
makerStrandSubmit,
|
|
1639
1815
|
makerCurrentPrepare,
|
|
1640
1816
|
makerCurrentSubmit,
|
|
1641
|
-
|
|
1642
|
-
|
|
1817
|
+
];
|
|
1818
|
+
applyToolAvailability(registeredTools, initialCatalog, initialPlatformCatalog);
|
|
1643
1819
|
let closed = false;
|
|
1644
1820
|
const refresh = async () => {
|
|
1645
1821
|
if (closed)
|
|
1646
1822
|
return;
|
|
1647
|
-
|
|
1823
|
+
const [catalog, platformCatalog] = await Promise.all([
|
|
1824
|
+
client.capabilities(),
|
|
1825
|
+
platformClient.discovery.read(),
|
|
1826
|
+
]);
|
|
1827
|
+
applyToolAvailability(registeredTools, catalog, platformCatalog);
|
|
1648
1828
|
};
|
|
1649
1829
|
const timer = setInterval(() => {
|
|
1650
1830
|
refresh().catch((error) => {
|
|
@@ -1662,10 +1842,10 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1662
1842
|
},
|
|
1663
1843
|
};
|
|
1664
1844
|
}
|
|
1665
|
-
function registerAutonomyTools(
|
|
1845
|
+
function registerAutonomyTools(registerTool, client, platformClient, autonomy, nowMs) {
|
|
1666
1846
|
// Always present, always read-only: the agent may show the slider and offer
|
|
1667
1847
|
// to change it, but nothing it calls can raise its own autonomy.
|
|
1668
|
-
|
|
1848
|
+
registerTool("strata_autonomy", {
|
|
1669
1849
|
title: "Strata session autonomy",
|
|
1670
1850
|
description: "Read how much this MCP may finish by itself: the autonomy level (ask / limits / instant), "
|
|
1671
1851
|
+ "any USD ceilings, and how to change it. Read-only — the level is the user's, set out-of-band "
|
|
@@ -1730,7 +1910,7 @@ function registerAutonomyTools(server, client, platformClient, autonomy, nowMs)
|
|
|
1730
1910
|
};
|
|
1731
1911
|
const refuse = (reason, prepared, summary) => toolResult({ executed: false, reason, prepared }, summary);
|
|
1732
1912
|
// ── one-shot immediate execution from a fresh Sonar quote ─────────────────
|
|
1733
|
-
|
|
1913
|
+
registerTool("strata_execute_quote", {
|
|
1734
1914
|
title: "Execute a Strata quote",
|
|
1735
1915
|
description: "Take a fresh Sonar quote and, within the autonomy slider, sign it with the session key and "
|
|
1736
1916
|
+ "submit it in one call. Under \"ask\" (or over a \"limits\" ceiling) it does not sign — it returns "
|
|
@@ -1775,7 +1955,7 @@ function registerAutonomyTools(server, client, platformClient, autonomy, nowMs)
|
|
|
1775
1955
|
return toolResult({ executed: true, receipt, notional_usd: notional }, `Executed ${quote.side} on ${quote.market_id} as ${receipt.signature}.`);
|
|
1776
1956
|
}));
|
|
1777
1957
|
// ── one-shot order control (place / cancel / replace / batch) ─────────────
|
|
1778
|
-
|
|
1958
|
+
registerTool("strata_order_execute", {
|
|
1779
1959
|
title: "Execute a Strata order control",
|
|
1780
1960
|
description: "Place, cancel, replace, or batch orders and, within the autonomy slider, sign with the session "
|
|
1781
1961
|
+ "key and submit in one call. Owner wallet and session key come from the configured session. "
|
|
@@ -1837,7 +2017,7 @@ function registerAutonomyTools(server, client, platformClient, autonomy, nowMs)
|
|
|
1837
2017
|
return toolResult({ executed: true, receipt, notional_usd: notional }, `Executed ${receipt.action} control ${receipt.order_control_id} as ${receipt.signature}.`);
|
|
1838
2018
|
}));
|
|
1839
2019
|
// ── one-shot TWAP (schedule / cancel) ─────────────────────────────────────
|
|
1840
|
-
|
|
2020
|
+
registerTool("strata_twap_execute", {
|
|
1841
2021
|
title: "Execute a Strata TWAP",
|
|
1842
2022
|
description: "Schedule or cancel a TWAP and, within the autonomy slider, sign with the session key and submit "
|
|
1843
2023
|
+ "in one call. Owner wallet and session key come from the configured session. Under \"ask\" (or over "
|
|
@@ -1860,7 +2040,7 @@ function registerAutonomyTools(server, client, platformClient, autonomy, nowMs)
|
|
|
1860
2040
|
idempotentHint: false,
|
|
1861
2041
|
openWorldHint: true,
|
|
1862
2042
|
},
|
|
1863
|
-
}, async (args) =>
|
|
2043
|
+
}, async (args) => safeTool(async () => {
|
|
1864
2044
|
let operation;
|
|
1865
2045
|
if (args.action === "cancel") {
|
|
1866
2046
|
if (args.twapId === undefined)
|
|
@@ -1909,23 +2089,36 @@ function registerAutonomyTools(server, client, platformClient, autonomy, nowMs)
|
|
|
1909
2089
|
return toolResult({ executed: true, receipt, notional_usd: notional }, `Executed TWAP ${receipt.twap_control_id} as ${receipt.signature}.`);
|
|
1910
2090
|
}));
|
|
1911
2091
|
}
|
|
1912
|
-
function
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2092
|
+
function trackedToolRegistrar(server) {
|
|
2093
|
+
const handles = new Map();
|
|
2094
|
+
const register = server.registerTool.bind(server);
|
|
2095
|
+
const registerTool = ((...args) => {
|
|
2096
|
+
const tool = register(...args);
|
|
2097
|
+
const name = args[0];
|
|
2098
|
+
if (typeof name === "string")
|
|
2099
|
+
handles.set(name, tool);
|
|
2100
|
+
return tool;
|
|
2101
|
+
});
|
|
2102
|
+
return { registerTool, handles };
|
|
2103
|
+
}
|
|
2104
|
+
function platformCapabilityAvailable(catalog, id) {
|
|
2105
|
+
return catalog.capabilities.some((capability) => capability.id === id
|
|
2106
|
+
&& capability.transports.includes("mcp")
|
|
2107
|
+
&& capability.mcp_exposure !== "none");
|
|
2108
|
+
}
|
|
2109
|
+
function requirementAvailable(requirement, available) {
|
|
2110
|
+
if (requirement === undefined)
|
|
2111
|
+
return true;
|
|
2112
|
+
return requirement.match === "any"
|
|
2113
|
+
? requirement.ids.some(available)
|
|
2114
|
+
: requirement.ids.every(available);
|
|
2115
|
+
}
|
|
2116
|
+
function applyToolAvailability(handles, catalog, platformCatalog) {
|
|
2117
|
+
for (const [name, tool] of handles) {
|
|
2118
|
+
const legacyAvailable = requirementAvailable(LEGACY_TOOL_CAPABILITIES[name], (id) => capabilityAvailable(catalog, id));
|
|
2119
|
+
const platformAvailable = requirementAvailable(PLATFORM_TOOL_CAPABILITIES[name], (id) => platformCapabilityAvailable(platformCatalog, id));
|
|
2120
|
+
setToolEnabled(tool, legacyAvailable && platformAvailable);
|
|
2121
|
+
}
|
|
1929
2122
|
}
|
|
1930
2123
|
function setToolEnabled(tool, enabled) {
|
|
1931
2124
|
if (enabled)
|
|
@@ -1948,6 +2141,17 @@ async function guardedTool(client, capabilityId, operation) {
|
|
|
1948
2141
|
return toolError("request_failed", safeMessage(error), true);
|
|
1949
2142
|
}
|
|
1950
2143
|
}
|
|
2144
|
+
async function safeTool(operation) {
|
|
2145
|
+
try {
|
|
2146
|
+
return await operation();
|
|
2147
|
+
}
|
|
2148
|
+
catch (error) {
|
|
2149
|
+
if (error instanceof StrataApiError) {
|
|
2150
|
+
return toolError(error.code, error.message, error.retryable);
|
|
2151
|
+
}
|
|
2152
|
+
return toolError("request_failed", safeMessage(error), true);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
1951
2155
|
/**
|
|
1952
2156
|
* One line that keeps the two numbers apart: price impact is measured from the
|
|
1953
2157
|
* book; the tolerance is the caller's own floor.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratabook/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Connect AI agents to Strata markets and Sonar quotes with MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
47
|
-
"@stratabook/sdk": "0.2.
|
|
47
|
+
"@stratabook/sdk": "0.2.5",
|
|
48
48
|
"zod": "^3.25.76"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|