@stratabook/mcp 0.2.0 → 0.2.2
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.
|
@@ -188,7 +188,7 @@ export declare const STRATA_ACTION_GRAPH: {
|
|
|
188
188
|
}, {
|
|
189
189
|
readonly id: "read_market_status";
|
|
190
190
|
readonly kind: "read";
|
|
191
|
-
readonly summary: "Read tick size,
|
|
191
|
+
readonly summary: "Read tick size, the smallest valid base-atom size, and current market status.";
|
|
192
192
|
readonly required_capabilities: readonly ["books.read"];
|
|
193
193
|
readonly available: true;
|
|
194
194
|
readonly operation: {
|
|
@@ -325,7 +325,7 @@ export const STRATA_ACTION_GRAPH = {
|
|
|
325
325
|
{
|
|
326
326
|
"id": "read_market_status",
|
|
327
327
|
"kind": "read",
|
|
328
|
-
"summary": "Read tick size,
|
|
328
|
+
"summary": "Read tick size, the smallest valid base-atom size, and current market status.",
|
|
329
329
|
"required_capabilities": [
|
|
330
330
|
"books.read"
|
|
331
331
|
],
|
package/dist/src/server.js
CHANGED
|
@@ -1443,6 +1443,185 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1443
1443
|
const response = await platformClient.orders.status(marketId, { orderControlId, idempotencyKey });
|
|
1444
1444
|
return toolResult(response, `Order control ${response.order_control_id} is ${response.status}.`);
|
|
1445
1445
|
}));
|
|
1446
|
+
const makerStrandPrepare = server.registerTool("strata_market_making_strand_prepare", {
|
|
1447
|
+
title: "Prepare Strata Strand control",
|
|
1448
|
+
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
|
+
inputSchema: {
|
|
1450
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
1451
|
+
action: z.enum(["upsert", "recenter", "set_enabled", "cancel"]),
|
|
1452
|
+
makerWallet: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/),
|
|
1453
|
+
enabled: z.boolean().optional(),
|
|
1454
|
+
asyncOnly: z.boolean().optional(),
|
|
1455
|
+
syncSpreadTicks: z.number().int().min(0).max(65_535).optional(),
|
|
1456
|
+
midPriceAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
1457
|
+
maxExposureBaseAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
1458
|
+
bidOffsetsTicks: z.array(z.number().int().min(0).max(65_535)).length(16).optional(),
|
|
1459
|
+
askOffsetsTicks: z.array(z.number().int().min(0).max(65_535)).length(16).optional(),
|
|
1460
|
+
bidSizesBaseAtoms: z.array(z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20)).length(16).optional(),
|
|
1461
|
+
askSizesBaseAtoms: z.array(z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20)).length(16).optional(),
|
|
1462
|
+
newMidPriceAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
1463
|
+
validUntilSlot: z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20).optional(),
|
|
1464
|
+
},
|
|
1465
|
+
annotations: {
|
|
1466
|
+
readOnlyHint: false,
|
|
1467
|
+
destructiveHint: true,
|
|
1468
|
+
idempotentHint: false,
|
|
1469
|
+
openWorldHint: true,
|
|
1470
|
+
},
|
|
1471
|
+
}, async (args) => guardedTool(client, "mm.strand.manage", async () => {
|
|
1472
|
+
let request;
|
|
1473
|
+
if (args.action === "upsert") {
|
|
1474
|
+
if (args.enabled === undefined || args.asyncOnly === undefined
|
|
1475
|
+
|| args.syncSpreadTicks === undefined || args.midPriceAtoms === undefined
|
|
1476
|
+
|| args.maxExposureBaseAtoms === undefined || args.bidOffsetsTicks === undefined
|
|
1477
|
+
|| args.askOffsetsTicks === undefined || args.bidSizesBaseAtoms === undefined
|
|
1478
|
+
|| args.askSizesBaseAtoms === undefined || args.validUntilSlot === undefined) {
|
|
1479
|
+
return toolError("invalid_request", "Strand upsert requires every level, exposure, midpoint, spread, flag, and expiry field.", false);
|
|
1480
|
+
}
|
|
1481
|
+
request = {
|
|
1482
|
+
action: "upsert",
|
|
1483
|
+
makerWallet: args.makerWallet,
|
|
1484
|
+
enabled: args.enabled,
|
|
1485
|
+
asyncOnly: args.asyncOnly,
|
|
1486
|
+
syncSpreadTicks: args.syncSpreadTicks,
|
|
1487
|
+
midPriceAtoms: args.midPriceAtoms,
|
|
1488
|
+
maxExposureBaseAtoms: args.maxExposureBaseAtoms,
|
|
1489
|
+
bidOffsetsTicks: args.bidOffsetsTicks,
|
|
1490
|
+
askOffsetsTicks: args.askOffsetsTicks,
|
|
1491
|
+
bidSizesBaseAtoms: args.bidSizesBaseAtoms,
|
|
1492
|
+
askSizesBaseAtoms: args.askSizesBaseAtoms,
|
|
1493
|
+
validUntilSlot: args.validUntilSlot,
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
else if (args.action === "recenter") {
|
|
1497
|
+
if (args.newMidPriceAtoms === undefined || args.validUntilSlot === undefined) {
|
|
1498
|
+
return toolError("invalid_request", "Strand recenter requires newMidPriceAtoms and validUntilSlot.", false);
|
|
1499
|
+
}
|
|
1500
|
+
request = {
|
|
1501
|
+
action: "recenter",
|
|
1502
|
+
makerWallet: args.makerWallet,
|
|
1503
|
+
newMidPriceAtoms: args.newMidPriceAtoms,
|
|
1504
|
+
validUntilSlot: args.validUntilSlot,
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
else if (args.action === "set_enabled") {
|
|
1508
|
+
if (args.enabled === undefined) {
|
|
1509
|
+
return toolError("invalid_request", "Strand set_enabled requires enabled.", false);
|
|
1510
|
+
}
|
|
1511
|
+
request = { action: "set_enabled", makerWallet: args.makerWallet, enabled: args.enabled };
|
|
1512
|
+
}
|
|
1513
|
+
else {
|
|
1514
|
+
request = { action: "cancel", makerWallet: args.makerWallet };
|
|
1515
|
+
}
|
|
1516
|
+
const response = await platformClient.marketMaking.strand.prepare(args.marketId, request);
|
|
1517
|
+
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
|
+
}));
|
|
1519
|
+
const makerStrandSubmit = server.registerTool("strata_market_making_strand_submit", {
|
|
1520
|
+
title: "Submit Strata Strand control",
|
|
1521
|
+
description: "Submit the exact externally maker-signed Strand transaction with a stable retry key.",
|
|
1522
|
+
inputSchema: {
|
|
1523
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
1524
|
+
makerControlId: z.string().regex(/^mc_[0-9a-f]{32}$/),
|
|
1525
|
+
signedTransactionBase64: z.string().min(4).max(4_096).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
|
|
1526
|
+
idempotencyKey: z.string().min(1).max(64).regex(/^[A-Za-z0-9._-]+$/),
|
|
1527
|
+
},
|
|
1528
|
+
annotations: {
|
|
1529
|
+
readOnlyHint: false,
|
|
1530
|
+
destructiveHint: true,
|
|
1531
|
+
idempotentHint: true,
|
|
1532
|
+
openWorldHint: true,
|
|
1533
|
+
},
|
|
1534
|
+
}, async ({ marketId, makerControlId, signedTransactionBase64, idempotencyKey }) => guardedTool(client, "mm.strand.manage", async () => {
|
|
1535
|
+
const response = await platformClient.marketMaking.strand.submit(marketId, {
|
|
1536
|
+
makerControlId,
|
|
1537
|
+
signedTransactionBase64,
|
|
1538
|
+
idempotencyKey,
|
|
1539
|
+
});
|
|
1540
|
+
return toolResult(response, `Submitted ${response.action} as ${response.signature}.`);
|
|
1541
|
+
}));
|
|
1542
|
+
const makerCurrentPrepare = server.registerTool("strata_market_making_current_prepare", {
|
|
1543
|
+
title: "Prepare Strata Current control",
|
|
1544
|
+
description: "Build one exact unsigned maker-owned Current transaction. Upsert fails closed until the market has a verified on-chain reference; cancel does not need that reference.",
|
|
1545
|
+
inputSchema: {
|
|
1546
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
1547
|
+
action: z.enum(["upsert", "cancel"]),
|
|
1548
|
+
makerWallet: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/),
|
|
1549
|
+
enabled: z.boolean().optional(),
|
|
1550
|
+
asyncOnly: z.boolean().optional(),
|
|
1551
|
+
halfSpreadBps: z.number().int().min(1).max(65_535).optional(),
|
|
1552
|
+
bandStepBps: z.number().int().min(0).max(65_535).optional(),
|
|
1553
|
+
maxConfidenceBps: z.number().int().min(1).max(100).optional(),
|
|
1554
|
+
maxOracleDeviationBps: z.number().int().min(1).max(500).optional(),
|
|
1555
|
+
maxOracleAgeSeconds: z.number().int().min(0).max(4_294_967_295).optional(),
|
|
1556
|
+
syncSpreadBps: z.number().int().min(0).max(65_535).optional(),
|
|
1557
|
+
maxExposureBaseAtoms: z.string().regex(/^[1-9][0-9]*$/).max(20).optional(),
|
|
1558
|
+
bidDepthBaseAtoms: z.array(z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20)).length(8).optional(),
|
|
1559
|
+
askDepthBaseAtoms: z.array(z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20)).length(8).optional(),
|
|
1560
|
+
validUntilSlot: z.string().regex(/^(?:0|[1-9][0-9]*)$/).max(20).optional(),
|
|
1561
|
+
},
|
|
1562
|
+
annotations: {
|
|
1563
|
+
readOnlyHint: false,
|
|
1564
|
+
destructiveHint: true,
|
|
1565
|
+
idempotentHint: false,
|
|
1566
|
+
openWorldHint: true,
|
|
1567
|
+
},
|
|
1568
|
+
}, async (args) => guardedTool(client, "mm.current.manage", async () => {
|
|
1569
|
+
let request;
|
|
1570
|
+
if (args.action === "cancel") {
|
|
1571
|
+
request = { action: "cancel", makerWallet: args.makerWallet };
|
|
1572
|
+
}
|
|
1573
|
+
else {
|
|
1574
|
+
if (args.enabled === undefined || args.asyncOnly === undefined
|
|
1575
|
+
|| args.halfSpreadBps === undefined || args.bandStepBps === undefined
|
|
1576
|
+
|| args.maxConfidenceBps === undefined || args.maxOracleDeviationBps === undefined
|
|
1577
|
+
|| args.maxOracleAgeSeconds === undefined || args.syncSpreadBps === undefined
|
|
1578
|
+
|| args.maxExposureBaseAtoms === undefined || args.bidDepthBaseAtoms === undefined
|
|
1579
|
+
|| args.askDepthBaseAtoms === undefined || args.validUntilSlot === undefined) {
|
|
1580
|
+
return toolError("invalid_request", "Current upsert requires every depth, exposure, spread, oracle-bound, flag, and expiry field.", false);
|
|
1581
|
+
}
|
|
1582
|
+
request = {
|
|
1583
|
+
action: "upsert",
|
|
1584
|
+
makerWallet: args.makerWallet,
|
|
1585
|
+
enabled: args.enabled,
|
|
1586
|
+
asyncOnly: args.asyncOnly,
|
|
1587
|
+
halfSpreadBps: args.halfSpreadBps,
|
|
1588
|
+
bandStepBps: args.bandStepBps,
|
|
1589
|
+
maxConfidenceBps: args.maxConfidenceBps,
|
|
1590
|
+
maxOracleDeviationBps: args.maxOracleDeviationBps,
|
|
1591
|
+
maxOracleAgeSeconds: args.maxOracleAgeSeconds,
|
|
1592
|
+
syncSpreadBps: args.syncSpreadBps,
|
|
1593
|
+
maxExposureBaseAtoms: args.maxExposureBaseAtoms,
|
|
1594
|
+
bidDepthBaseAtoms: args.bidDepthBaseAtoms,
|
|
1595
|
+
askDepthBaseAtoms: args.askDepthBaseAtoms,
|
|
1596
|
+
validUntilSlot: args.validUntilSlot,
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
const response = await platformClient.marketMaking.current.prepare(args.marketId, request);
|
|
1600
|
+
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
|
+
}));
|
|
1602
|
+
const makerCurrentSubmit = server.registerTool("strata_market_making_current_submit", {
|
|
1603
|
+
title: "Submit Strata Current control",
|
|
1604
|
+
description: "Submit the exact externally maker-signed Current transaction with a stable retry key.",
|
|
1605
|
+
inputSchema: {
|
|
1606
|
+
marketId: z.string().regex(/^market_[0-9a-f]{32}$/),
|
|
1607
|
+
makerControlId: z.string().regex(/^mc_[0-9a-f]{32}$/),
|
|
1608
|
+
signedTransactionBase64: z.string().min(4).max(4_096).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/),
|
|
1609
|
+
idempotencyKey: z.string().min(1).max(64).regex(/^[A-Za-z0-9._-]+$/),
|
|
1610
|
+
},
|
|
1611
|
+
annotations: {
|
|
1612
|
+
readOnlyHint: false,
|
|
1613
|
+
destructiveHint: true,
|
|
1614
|
+
idempotentHint: true,
|
|
1615
|
+
openWorldHint: true,
|
|
1616
|
+
},
|
|
1617
|
+
}, async ({ marketId, makerControlId, signedTransactionBase64, idempotencyKey }) => guardedTool(client, "mm.current.manage", async () => {
|
|
1618
|
+
const response = await platformClient.marketMaking.current.submit(marketId, {
|
|
1619
|
+
makerControlId,
|
|
1620
|
+
signedTransactionBase64,
|
|
1621
|
+
idempotencyKey,
|
|
1622
|
+
});
|
|
1623
|
+
return toolResult(response, `Submitted ${response.action} as ${response.signature}.`);
|
|
1624
|
+
}));
|
|
1446
1625
|
registerAutonomyTools(server, client, platformClient, options.sessionAutonomy, () => typeof Date !== "undefined" ? Date.now() : 0);
|
|
1447
1626
|
const handles = {
|
|
1448
1627
|
markets,
|
|
@@ -1455,6 +1634,10 @@ export async function createStrataMcpServer(options = {}) {
|
|
|
1455
1634
|
orderPrepare,
|
|
1456
1635
|
orderSubmit,
|
|
1457
1636
|
orderStatus,
|
|
1637
|
+
makerStrandPrepare,
|
|
1638
|
+
makerStrandSubmit,
|
|
1639
|
+
makerCurrentPrepare,
|
|
1640
|
+
makerCurrentSubmit,
|
|
1458
1641
|
};
|
|
1459
1642
|
applyCapabilityCatalog(handles, initialCatalog);
|
|
1460
1643
|
let closed = false;
|
|
@@ -1737,6 +1920,12 @@ function applyCapabilityCatalog(handles, catalog) {
|
|
|
1737
1920
|
setToolEnabled(handles.orderPrepare, capabilityAvailable(catalog, "orders.prepare"));
|
|
1738
1921
|
setToolEnabled(handles.orderSubmit, capabilityAvailable(catalog, "orders.submit"));
|
|
1739
1922
|
setToolEnabled(handles.orderStatus, capabilityAvailable(catalog, "orders.submit"));
|
|
1923
|
+
const strandEnabled = capabilityAvailable(catalog, "mm.strand.manage");
|
|
1924
|
+
setToolEnabled(handles.makerStrandPrepare, strandEnabled);
|
|
1925
|
+
setToolEnabled(handles.makerStrandSubmit, strandEnabled);
|
|
1926
|
+
const currentEnabled = capabilityAvailable(catalog, "mm.current.manage");
|
|
1927
|
+
setToolEnabled(handles.makerCurrentPrepare, currentEnabled);
|
|
1928
|
+
setToolEnabled(handles.makerCurrentSubmit, currentEnabled);
|
|
1740
1929
|
}
|
|
1741
1930
|
function setToolEnabled(tool, enabled) {
|
|
1742
1931
|
if (enabled)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratabook/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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.2",
|
|
48
48
|
"zod": "^3.25.76"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|