@zktx.io/sui-mcp 0.6.2 → 0.8.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 +94 -52
- package/dist/adapters/adapterPromptSurfaces.js +1 -1
- package/dist/core/activity/localDataService.js +8 -21
- package/dist/core/activity/localDataValidation.js +22 -46
- package/dist/core/activity/sqliteAccountStore.js +46 -0
- package/dist/core/activity/sqliteActivityStore.js +65 -147
- package/dist/core/activity/sqliteActivityStoreSchema.js +42 -26
- package/dist/core/activity/transactionActivityService.js +2 -2
- package/dist/core/preferences/preferencesStore.js +2 -2
- package/dist/core/preferences/sqlitePreferencesRepository.js +10 -0
- package/dist/core/read/deepbookReadHelpers.js +1 -1
- package/dist/core/read/readResponseGuidance.js +6 -6
- package/dist/core/session/cardResult.js +41 -0
- package/dist/core/session/cardSession.js +1 -1
- package/dist/core/session/cardSessionStore.js +51 -19
- package/dist/core/session/chainAccounts.js +120 -0
- package/dist/core/session/sessionStore.js +4 -8
- package/dist/core/session/settingsFileProtocol.js +1 -1
- package/dist/core/session/settingsFileStore.js +3 -30
- package/dist/core/session/settingsOperation.js +27 -19
- package/dist/core/session/settingsWorkflow.js +161 -87
- package/dist/core/session/sqliteCardStore.js +34 -14
- package/dist/core/session/sqliteSessionStore.js +5 -5
- package/dist/core/session/sqliteSettingsWorkflowStore.js +135 -41
- package/dist/core/session/sqliteTransactionRequest.js +18 -0
- package/dist/core/session/sqliteWalletConnectionOperation.js +13 -0
- package/dist/core/session/sqliteWalletWorkflowStore.js +569 -333
- package/dist/core/session/status.js +2 -2
- package/dist/core/session/wait.js +6 -11
- package/dist/core/session/walletConnection.js +71 -46
- package/dist/core/session/walletConnectionOperations.js +24 -0
- package/dist/core/session/walletRuntime.js +7 -13
- package/dist/core/session/walletWorkflow.js +248 -99
- package/dist/core/session/workflowState.js +104 -38
- package/dist/core/session/workflowView.js +92 -101
- package/dist/mcp/activeAccountResponse.js +3 -0
- package/dist/mcp/prompts.js +10 -4
- package/dist/mcp/resources.js +1 -1
- package/dist/mcp/responseGuidance.js +7 -9
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/serverInfo.js +21 -19
- package/dist/mcp/toolErrors.js +5 -3
- package/dist/mcp/toolNames.js +47 -46
- package/dist/mcp/tools/action/prepareSuiActionReview.js +13 -20
- package/dist/mcp/tools/read/deepbookReadTools.js +1 -1
- package/dist/mcp/tools/read/index.js +2 -2
- package/dist/mcp/tools/read/readToolHelpers.js +9 -7
- package/dist/mcp/tools/read/serverStatusTools.js +4 -5
- package/dist/mcp/tools/read/transactionActivityTools.js +3 -3
- package/dist/mcp/tools/session/executionResultTools.js +2 -2
- package/dist/mcp/tools/session/shared.js +2 -2
- package/dist/mcp/tools/session/statusTools.js +12 -10
- package/dist/mcp/tools/session/walletConnectionTools.js +29 -17
- package/dist/mcp/tools/settings/index.js +7 -4
- package/dist/mcp-app/account.html +7 -7
- package/dist/mcp-app/chart.html +3 -3
- package/dist/mcp-app/connect.html +13 -13
- package/dist/mcp-app/disconnect.html +3637 -0
- package/dist/mcp-app/disconnect.notices.txt +1480 -0
- package/dist/mcp-app/receipt.html +393 -393
- package/dist/mcp-app/review.html +459 -459
- package/dist/mcp-app/settings.html +7 -7
- package/dist/mcp-ui/contracts.js +3 -1
- package/dist/mcp-ui/tools.js +4 -4
- package/dist/runtime/application.js +3 -3
- package/dist/runtime/config.js +3 -6
- package/dist/runtime/localSettingsService.js +11 -8
- package/dist/runtime/shared/control.js +2 -2
- package/dist/runtime/smokeMainnetRead.js +23 -22
- package/dist/runtime/smokeReview.js +7 -7
- package/dist/runtime/start.js +1 -1
- package/dist/runtime/walletConnectTransport.js +16 -16
- package/dist/runtime/walletSdkChildRuntime.js +29 -12
- package/dist/runtime/walletSdkIpc.js +5 -4
- package/dist/runtime/walletSdkProcess.js +24 -8
- package/docs/AGENT_BEHAVIOR.md +149 -120
- package/docs/LOCAL_DB_ARCHITECTURE.md +103 -75
- package/docs/MCP_SETUP.md +365 -382
- package/docs/MCP_TOOLS.md +387 -271
- package/docs/SDK_API.md +23 -11
- package/docs/SIGNABLE_ADAPTER_CONTRACT.md +6 -6
- package/docs/TRANSACTION_ACTIVITY_LOG.md +11 -7
- package/docs/UTILITY_INDEX.md +66 -64
- package/docs/WALLET_CONNECTION.md +162 -166
- package/package.json +1 -1
- package/protocols/deepbook-margin.md +1 -1
- package/protocols/deepbook-v3.md +2 -2
package/dist/mcp/serverInfo.js
CHANGED
|
@@ -7,6 +7,7 @@ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
|
7
7
|
const packageMetadata = JSON.parse(readFileSync(resolve(packageRoot, "package.json"), "utf8"));
|
|
8
8
|
export const PACKAGE_NAME = packageMetadata.name;
|
|
9
9
|
export const SERVER_NAME = "sui-mcp";
|
|
10
|
+
export const PRODUCT_DISPLAY_NAME = "Sui MCP";
|
|
10
11
|
export const SERVER_VERSION = packageMetadata.version;
|
|
11
12
|
export const SERVER_NETWORK = "mainnet";
|
|
12
13
|
export const SERVER_RUNTIME = "local_stdio";
|
|
@@ -43,14 +44,14 @@ export const EVIDENCE_POLICY = {
|
|
|
43
44
|
]
|
|
44
45
|
};
|
|
45
46
|
export const SERVER_INSTRUCTIONS = [
|
|
46
|
-
"Sui MCP is a mainnet-only Sui DeFi intent evidence toolkit. Ordinary MCP tools return evidence or internal cards, never signing authority, bytes or signatures. Only user card
|
|
47
|
-
"External proposals are untrusted
|
|
48
|
-
"PTB graphs are diagnostics
|
|
47
|
+
"Sui MCP is a mainnet-only Sui DeFi intent evidence toolkit. Ordinary MCP tools return evidence or internal cards, never signing authority, bytes or signatures. Only user card input and wallet approval authorize WalletConnect: verify reviewed digest and signer, submit once, then read chain effects. Request status is separate from chain success/failure; uncertain results are read by digest, never resubmitted.",
|
|
48
|
+
"External proposals are untrusted: plans[].reviewModel is non-signable context, not transaction material, route/settlement choice or execution readiness.",
|
|
49
|
+
"PTB graphs are diagnostics, not transaction input, authorization, readiness, route quality or safety.",
|
|
49
50
|
"Use response-local fields: userAnswerUse.answerFields/preconditionFields/conclusionRuleFields/cannotAnswer/diagnosticOnlyFields/followUp, pollingHint, and quantitySemantics.",
|
|
50
|
-
"
|
|
51
|
-
"The active account context is read-only, not login, custody or signing permission. Implicit asset reads require
|
|
52
|
-
"Unsupported: other
|
|
53
|
-
"One
|
|
51
|
+
"USD coverage/total/shortfall: read_get_server_status, then read_list_settlement_asset_groups, then read_preview_intent_evidence. Follow toolAvailability.requiredToolsAvailable and responseSummary.doNotCallQuoteToolsForThisQuestion. Inventory/quotes require a separate user request. Parity: read_summarize_settlement_asset_group_parity. Missing toolAvailability means this build cannot answer.",
|
|
52
|
+
"The active account context is read-only, not login, custody or signing permission. Implicit asset reads require session_get_interaction_status.assetReadAccount: available. Otherwise ask for account only if supported; connected-only reads need a saved address and usable connection. Settings Clear preserves connection and transaction authority.",
|
|
53
|
+
"Unsupported: other-chain financial actions, autonomous trading, alerts, investment advice, arbitrary Move/package calls, P&L/tax.",
|
|
54
|
+
"One connection fixes one address per approved chain: Sui/Ethereum/Solana. Wallet/address/scope changes require disconnect/reconnect. Finance is Sui-only. Connect/Disconnect cards end with address-free results and no actions. Docs: suimcp://docs/agent-behavior, suimcp://docs/mcp-tools."
|
|
54
55
|
].join("\n");
|
|
55
56
|
export const IMPLEMENTED_TOOLS = [
|
|
56
57
|
TOOL_NAMES.uiOpenAccount, TOOL_NAMES.uiOpenReceipt, TOOL_NAMES.uiOpenChart,
|
|
@@ -83,12 +84,13 @@ export const IMPLEMENTED_TOOLS = [
|
|
|
83
84
|
TOOL_NAMES.readGetAccountAssetTimeline,
|
|
84
85
|
TOOL_NAMES.settingsCreateLocalSettingsSession,
|
|
85
86
|
TOOL_NAMES.settingsGetLocalSettings,
|
|
86
|
-
TOOL_NAMES.
|
|
87
|
-
TOOL_NAMES.
|
|
87
|
+
TOOL_NAMES.actionStartReview,
|
|
88
|
+
TOOL_NAMES.actionCreateProposalReview,
|
|
88
89
|
TOOL_NAMES.accountGetActiveAccount,
|
|
89
|
-
TOOL_NAMES.
|
|
90
|
-
TOOL_NAMES.
|
|
91
|
-
TOOL_NAMES.
|
|
90
|
+
TOOL_NAMES.sessionOpenWalletConnectionCard,
|
|
91
|
+
TOOL_NAMES.sessionOpenWalletDisconnectionCard,
|
|
92
|
+
TOOL_NAMES.sessionGetWalletConnectionCard,
|
|
93
|
+
TOOL_NAMES.sessionWaitWalletConnectionCard,
|
|
92
94
|
TOOL_NAMES.sessionOpenReviewManagement,
|
|
93
95
|
TOOL_NAMES.sessionGetInteractionStatus,
|
|
94
96
|
TOOL_NAMES.sessionGetReviewStatus,
|
|
@@ -113,18 +115,18 @@ export function toolAvailability(requiredTools) {
|
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
117
|
export const SERVER_LIMITATIONS = [
|
|
116
|
-
"Current asset reads without a user-provided address require
|
|
118
|
+
"Current asset reads without a user-provided address require the fixed Sui address with a usable current wallet connection. session_get_interaction_status.assetReadAccount reports whether that default is available. Only tools with an account input accept explicit addresses; DeepBook account inventory requires the current connected Sui address. Explicit-address coin balance reads are public-address snapshots and do not create active account context. Active account is read context only, not signing authorization, login, custody, or persistent permission.",
|
|
117
119
|
"Review activity tools summarize local Sui MCP review evidence only. Sui activity tools use user-requested bounded GraphQL reads and store normalized transaction facts only for known wallet context; function activity scans are sent-transaction scans only. They are not background indexers, complete history, balance history, complete gas history, affected-object history, or P&L.",
|
|
118
|
-
`
|
|
120
|
+
`read_get_account_asset_timeline reads stored local account activity facts and returns observed raw net-flow bars with scan coverage. It does not start scans, prove complete wallet history, provide held balances without balanceBars, compute USD value, P&L, tax, cost basis, route advice, transaction-building input, signing data, or signing readiness. Optional USDC references are token-denominated ${DEEPBOOK_SOURCE_OWNER_RUNTIME_WORDING.officialIndexerCandleReferences} only, ${DEEPBOOK_SOURCE_OWNER_RUNTIME_WORDING.usdcNotFiatUsdAndNotPeg}.`,
|
|
119
121
|
"Sui activity transactionContext facts are transaction-level facts without transaction-wide balance-change aggregates, and they are answer fields only when the response returns them. requestedAccountTransactionFacts, requestedAccount, and requestedAccountEffect are the account-specific balance-change surfaces. Activity quantitySemantics marks balance amountRaw fields as raw integers that require verified decimals for display conversion. accountBalanceChangeInferencePolicy marks whether returned account balance rows can be used or transaction-level context must not be used for account amount inference. Gas raw fields use MIST, and returned gasCost display facts use @mysten/sui MIST_PER_SUI.",
|
|
120
122
|
"Wallet asset classification covers only current coin balances returned by Sui gRPC listBalances for an explicit address or the active account. Wallet balance quantitySemantics marks those reads as current snapshots, not transaction history, receipt proof, acquisition source, object provenance, P&L, cost basis, or signing material. DeepBook account inventory is a separate active-account read surface; neither surface creates routes, funding plans, portfolio plans, or signing material.",
|
|
121
123
|
"High-risk read responses include userAnswerUse. Prefer userAnswerUse.preconditionFields before answering, userAnswerUse.answerFields for the answer path, userAnswerUse.conclusionRuleFields for conclusion limits, userAnswerUse.diagnosticOnlyFields for source or troubleshooting context, and userAnswerUse.followUp when a different tool and field are required. USD intent and parity responses also include toolAvailability as a precondition field for current server-build support.",
|
|
122
124
|
"Intent evidence maps natural-language USD-denominated targets to pinned DeepBook SDK settlement asset groups and current wallet balance evidence. responseSummary.answerCompleteness names the answer class and required fields. Settlement-asset-only answers use responseSummary; selected-target evidence requires user selection provenance and also uses selectedTarget, candidateConversions, and requiredUserChoices when userAnswerUse.answerFields lists them. Direct pool quote evidence is returned and supported only when a quoted candidate exists. responseSummary.doNotUseForConclusion names quote results, outside-settlement-group assets, and route-dependent support as excluded from the conclusion. Intent evidence does not silently choose settlement assets, rank venues or routes, evaluate gas reserve, build transactions, or produce signing material.",
|
|
123
|
-
"DeepBook quotes convert explicit raw or display source inputs through pinned token units and return scoped SDK simulation facts plus raw quote evidence. Their quantitySemantics says canUseForPaymentAnswer and canUseForShortfallAnswer are false, doNotCombineWithPaymentAnswer is true, requiredPaymentAnswerTool is
|
|
124
|
-
"Action preparation returns internal Review cards. A current card with valid UI permission automatically prepares and renews verified conditions for
|
|
125
|
-
"
|
|
125
|
+
"DeepBook quotes convert explicit raw or display source inputs through pinned token units and return scoped SDK simulation facts plus raw quote evidence. Their quantitySemantics says canUseForPaymentAnswer and canUseForShortfallAnswer are false, doNotCombineWithPaymentAnswer is true, requiredPaymentAnswerTool is read_preview_intent_evidence, and requiredPaymentAnswerField is responseSummary.",
|
|
126
|
+
"Action preparation returns internal Review cards. A current card with valid UI permission automatically prepares and renews verified conditions for its original fixed wallet/account; only the explicit Request wallet approval action can request a signature. Supported DeepBook account-bound swap review verifies stored transaction material, digest, ownership, quote/policy, human-readable facts, simulation and PTB evidence. Only a scoped app-only user action and wallet approval authorize the backend WalletConnect request; ordinary MCP calls never sign or submit. Transaction bytes and signatures never enter card/model results. The backend verifies returned transaction digest and signer, submits once, and independently reads chain effects. requestStatus is separate from chain execution success/failure: stopped, request_failed and outcome_unknown do not prove a chain failure. Lost replies are resolved by reading the same request/digest, never automatic resubmission. External proposals remain non-signable. Receipts do not establish execution guarantees, route quality, fiat value, P&L, tax, peg proof or best-price advice.",
|
|
127
|
+
"read_list_deepbook_pools and read_list_deepbook_tokens return static SDK registry metadata, not live liquidity, live token discovery, or active pool state.",
|
|
126
128
|
`DeepBook orderbook, mid-price, and quote outputs are ${DEEPBOOK_SOURCE_OWNER_RUNTIME_WORDING.pinnedSdkSnapshots} at fetchedAt; treat them as stale if the user delays.`,
|
|
127
129
|
`DeepBook USDC price history and price-at-time reads use ${DEEPBOOK_SOURCE_OWNER_RUNTIME_WORDING.officialIndexerCandleData} for the requested official interval. They are external candle evidence only, not live quotes, historical mid prices, global market prices, fiat USD values, USDC/USD peg guarantees, route recommendations, transaction-building inputs, signing readiness, P&L, cost basis, user-account transaction history, or user-account balance history. Sui MCP does not independently recompute those candle values from chain history for the response.`,
|
|
128
|
-
`
|
|
129
|
-
"Settings uses an internal card. MCP settings tools create the card or read current settings; only the user's scoped card confirmation applies local changes or restarts the connection service. Backup bytes stay in app-only file transfer. No external Settings URL exists."
|
|
130
|
+
`ui_open_chart displays ${DEEPBOOK_SOURCE_OWNER_RUNTIME_WORDING.officialIndexerUsdcDenominatedCandles} in an internal read-only card. ui_open_account displays a public-address asset snapshot; ui_open_receipt displays the executed transaction graph when bound UI metadata is available, followed by on-chain facts and a Details slide. Card inputs end after backend admission, expiry or invalidation; chat navigation and frame recreation do not end valid unsubmitted input. Read the same DB state after a lost reply rather than resubmitting. Saved results do not authorize a new query or transaction. These cards are not live feeds, trading interfaces, route recommendations, fiat USD value, P&L, tax, cost basis, signing data, or signing readiness.`,
|
|
131
|
+
"Settings uses an internal card. MCP settings tools create the card or read current settings; only the user's scoped card confirmation applies local changes or restarts the connection service. Backup bytes stay in app-only file transfer. Closed cards are immutable; another delivery requires a new backupDelivery card for the same retained snapshot, and operationStatus records current cleanup without repeating an effect. No external Settings URL exists."
|
|
130
132
|
];
|
package/dist/mcp/toolErrors.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SettingsConflict } from "../core/session/settingsOperation.js";
|
|
1
2
|
import { WalletUnavailableError } from "../core/session/walletConnection.js";
|
|
2
3
|
import { WorkflowConflict } from "../core/session/sqliteWalletWorkflowStore.js";
|
|
3
4
|
import { CardError } from "../core/session/cardSessionStore.js";
|
|
@@ -47,9 +48,10 @@ export function transactionActivityToolError(error, logger) {
|
|
|
47
48
|
export function sessionDomainToolError(error) {
|
|
48
49
|
if (error instanceof WalletUnavailableError)
|
|
49
50
|
return errorToolResult({ kind: "wallet_unavailable",
|
|
50
|
-
details: {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
details: { ...(error.availability.status === "unavailable" ? { reason: error.availability.reason } : {}),
|
|
52
|
+
message: error.message, walletAvailability: error.availability } });
|
|
53
|
+
if (error instanceof WorkflowConflict || error instanceof CardError || error instanceof SettingsConflict) {
|
|
54
|
+
return errorToolResult({ kind: "input_invalid", details: { reason: error instanceof WorkflowConflict ? error.reason ?? error.message : error.message, message: error.message } });
|
|
53
55
|
}
|
|
54
56
|
if (error instanceof WaitRequestAbortedError) {
|
|
55
57
|
return errorToolResult({
|
package/dist/mcp/toolNames.js
CHANGED
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
export const TOOL_NAMES = {
|
|
2
|
-
uiOpenAccount: "
|
|
3
|
-
uiOpenReceipt: "
|
|
4
|
-
uiOpenChart: "
|
|
5
|
-
uiReadCard: "
|
|
6
|
-
uiSubmitCard: "
|
|
7
|
-
uiActCard: "
|
|
8
|
-
uiReadSettingsFile: "
|
|
9
|
-
sessionOpenReviewManagement: "
|
|
10
|
-
readGetServerStatus: "
|
|
11
|
-
readListSupportedProtocols: "
|
|
12
|
-
readListDeepbookPools: "
|
|
13
|
-
readListDeepbookTokens: "
|
|
14
|
-
readInspectDeepbookOrderbook: "
|
|
15
|
-
readGetDeepbookMidPrice: "
|
|
16
|
-
readGetDeepbookUsdcPriceHistory: "
|
|
17
|
-
readGetDeepbookUsdcPriceAtTime: "
|
|
18
|
-
readQuoteDeepbookAction: "
|
|
19
|
-
readQuoteDeepbookDisplayAmount: "
|
|
20
|
-
readSummarizeDeepbookAccountInventory: "
|
|
21
|
-
readSummarizeWalletAssets: "
|
|
22
|
-
readClassifyWalletAssets: "
|
|
23
|
-
readListSettlementAssetGroups: "
|
|
24
|
-
readSummarizeSettlementAssetGroupParity: "
|
|
25
|
-
readPreviewIntentEvidence: "
|
|
26
|
-
readListReviewActivity: "
|
|
27
|
-
readSummarizeReviewFunnel: "
|
|
28
|
-
readGetReviewSessionDetail: "
|
|
29
|
-
readInspectSuiTransaction: "
|
|
30
|
-
readScanSuiAccountActivity: "
|
|
31
|
-
readSummarizeSuiActivityScan: "
|
|
32
|
-
readScanSuiFunctionActivity: "
|
|
33
|
-
readSummarizeSuiFunctionActivityScan: "
|
|
34
|
-
readSummarizeSuiAccountActivity: "
|
|
35
|
-
readGetAccountAssetTimeline: "
|
|
36
|
-
settingsCreateLocalSettingsSession: "
|
|
37
|
-
settingsGetLocalSettings: "
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
2
|
+
uiOpenAccount: "ui_open_account",
|
|
3
|
+
uiOpenReceipt: "ui_open_receipt",
|
|
4
|
+
uiOpenChart: "ui_open_chart",
|
|
5
|
+
uiReadCard: "ui_read_card",
|
|
6
|
+
uiSubmitCard: "ui_submit_card",
|
|
7
|
+
uiActCard: "ui_act_card",
|
|
8
|
+
uiReadSettingsFile: "ui_read_settings_file",
|
|
9
|
+
sessionOpenReviewManagement: "session_open_review_management",
|
|
10
|
+
readGetServerStatus: "read_get_server_status",
|
|
11
|
+
readListSupportedProtocols: "read_list_supported_protocols",
|
|
12
|
+
readListDeepbookPools: "read_list_deepbook_pools",
|
|
13
|
+
readListDeepbookTokens: "read_list_deepbook_tokens",
|
|
14
|
+
readInspectDeepbookOrderbook: "read_inspect_deepbook_orderbook",
|
|
15
|
+
readGetDeepbookMidPrice: "read_get_deepbook_mid_price",
|
|
16
|
+
readGetDeepbookUsdcPriceHistory: "read_get_deepbook_usdc_price_history",
|
|
17
|
+
readGetDeepbookUsdcPriceAtTime: "read_get_deepbook_usdc_price_at_time",
|
|
18
|
+
readQuoteDeepbookAction: "read_quote_deepbook_action",
|
|
19
|
+
readQuoteDeepbookDisplayAmount: "read_quote_deepbook_display_amount",
|
|
20
|
+
readSummarizeDeepbookAccountInventory: "read_summarize_deepbook_account_inventory",
|
|
21
|
+
readSummarizeWalletAssets: "read_summarize_wallet_assets",
|
|
22
|
+
readClassifyWalletAssets: "read_classify_wallet_assets",
|
|
23
|
+
readListSettlementAssetGroups: "read_list_settlement_asset_groups",
|
|
24
|
+
readSummarizeSettlementAssetGroupParity: "read_summarize_settlement_asset_group_parity",
|
|
25
|
+
readPreviewIntentEvidence: "read_preview_intent_evidence",
|
|
26
|
+
readListReviewActivity: "read_list_review_activity",
|
|
27
|
+
readSummarizeReviewFunnel: "read_summarize_review_funnel",
|
|
28
|
+
readGetReviewSessionDetail: "read_get_review_session_detail",
|
|
29
|
+
readInspectSuiTransaction: "read_inspect_sui_transaction",
|
|
30
|
+
readScanSuiAccountActivity: "read_scan_sui_account_activity",
|
|
31
|
+
readSummarizeSuiActivityScan: "read_summarize_sui_activity_scan",
|
|
32
|
+
readScanSuiFunctionActivity: "read_scan_sui_function_activity",
|
|
33
|
+
readSummarizeSuiFunctionActivityScan: "read_summarize_sui_function_activity_scan",
|
|
34
|
+
readSummarizeSuiAccountActivity: "read_summarize_sui_account_activity",
|
|
35
|
+
readGetAccountAssetTimeline: "read_get_account_asset_timeline",
|
|
36
|
+
settingsCreateLocalSettingsSession: "settings_create_local_settings_session",
|
|
37
|
+
settingsGetLocalSettings: "settings_get_local_settings",
|
|
38
|
+
actionStartReview: "action_start_review",
|
|
39
|
+
actionCreateProposalReview: "action_create_proposal_review",
|
|
40
|
+
sessionOpenWalletDisconnectionCard: "session_open_wallet_disconnection_card",
|
|
41
|
+
sessionOpenWalletConnectionCard: "session_open_wallet_connection_card",
|
|
42
|
+
sessionGetWalletConnectionCard: "session_get_wallet_connection_card",
|
|
43
|
+
sessionWaitWalletConnectionCard: "session_wait_wallet_connection_card",
|
|
44
|
+
sessionGetInteractionStatus: "session_get_interaction_status",
|
|
45
|
+
sessionGetReviewStatus: "session_get_review_status",
|
|
46
|
+
sessionGetExecutionResult: "session_get_execution_result",
|
|
47
|
+
sessionWaitExecutionResult: "session_wait_execution_result",
|
|
48
|
+
accountGetActiveAccount: "account_get_active_account"
|
|
48
49
|
};
|
|
49
50
|
export function assertValidToolName(name) {
|
|
50
51
|
if (!/^[A-Za-z0-9_.-]{1,128}$/.test(name)) {
|
|
@@ -9,16 +9,16 @@ import { prepareActionReviewUserAnswerUse, prepareExternalProposalReviewUserAnsw
|
|
|
9
9
|
import { registerSuiMcpTool } from "../../registerTool.js";
|
|
10
10
|
import { successOutputSchema } from "../../schemas.js";
|
|
11
11
|
import { errorToolResult } from "../../result.js";
|
|
12
|
-
import {
|
|
12
|
+
import { sessionStoreToolError } from "../../toolErrors.js";
|
|
13
13
|
import { TOOL_NAMES } from "../../toolNames.js";
|
|
14
14
|
import { userAnswerUseSchema } from "../read/commonSchemas.js";
|
|
15
15
|
export function registerActionTools(server, deps) {
|
|
16
|
-
server.registerTool(TOOL_NAMES.
|
|
17
|
-
title: "
|
|
16
|
+
server.registerTool(TOOL_NAMES.actionStartReview, {
|
|
17
|
+
title: "Start swap review",
|
|
18
18
|
description: "Create a local swap review session on a supported protocol. Returns an internal review card.",
|
|
19
19
|
inputSchema: z.object({
|
|
20
20
|
intent: swapIntentInputSchema
|
|
21
|
-
}),
|
|
21
|
+
}).strict(),
|
|
22
22
|
outputSchema: successOutputSchema({
|
|
23
23
|
reviewSessionId: z.string(),
|
|
24
24
|
card: cardSnapshotSchema,
|
|
@@ -32,19 +32,6 @@ export function registerActionTools(server, deps) {
|
|
|
32
32
|
if (!supportsCards(server))
|
|
33
33
|
return errorToolResult({ kind: "ui_unavailable", details: { reason: "An internal review card is required." } });
|
|
34
34
|
const now = new Date();
|
|
35
|
-
let activeAccount;
|
|
36
|
-
try {
|
|
37
|
-
activeAccount = await deps.activityStore.getActiveAccount();
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
return activityStoreToolError(error, deps.logger);
|
|
41
|
-
}
|
|
42
|
-
if (!activeAccount) {
|
|
43
|
-
return errorToolResult({
|
|
44
|
-
kind: "active_account_not_set",
|
|
45
|
-
details: { action: "connect_wallet_connection" }
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
35
|
const { protocol: protocolSlug, ...swapIntent } = intent;
|
|
49
36
|
const resolution = resolveIntentPlanFactory(INTENT_PLAN_FACTORIES, swapIntent.type, protocolSlug);
|
|
50
37
|
if (resolution.status !== "resolved") {
|
|
@@ -67,6 +54,12 @@ export function registerActionTools(server, deps) {
|
|
|
67
54
|
}
|
|
68
55
|
const plan = resolution.factory.createPlan(swapIntent, now);
|
|
69
56
|
try {
|
|
57
|
+
const target = deps.workflow?.resolveReviewTarget();
|
|
58
|
+
if (!target || target.status !== "available")
|
|
59
|
+
return errorToolResult({ kind: target?.reason === "wallet_unavailable" || !target ? "wallet_unavailable"
|
|
60
|
+
: target.reason === "connection_required" ? "active_account_not_set" : "input_invalid",
|
|
61
|
+
details: { reason: target?.reason ?? "wallet_unavailable", action: "check_exact_wallet_account",
|
|
62
|
+
message: "A fixed, currently usable Sui account and its exact connection are required for this review." } });
|
|
70
63
|
const { session } = await deps.sessions.createReviewSession([plan], now);
|
|
71
64
|
const preliminaryChecks = plan.preliminaryChecks ?? [];
|
|
72
65
|
const hasBlockingPreliminaryChecks = preliminaryChecks.some((check) => check.status === "fail");
|
|
@@ -76,14 +69,14 @@ export function registerActionTools(server, deps) {
|
|
|
76
69
|
preliminaryChecks,
|
|
77
70
|
userAnswerUse: prepareActionReviewUserAnswerUse({ hasBlockingPreliminaryChecks })
|
|
78
71
|
};
|
|
79
|
-
return await createWorkflowCard(server, deps, "review", { reviewSessionId: session.id }, payload);
|
|
72
|
+
return await createWorkflowCard(server, deps, "review", { reviewSessionId: session.id, connectionId: target.connectionId, account: target.account }, payload);
|
|
80
73
|
}
|
|
81
74
|
catch (error) {
|
|
82
75
|
return sessionStoreToolError(error, deps.logger);
|
|
83
76
|
}
|
|
84
77
|
});
|
|
85
|
-
registerSuiMcpTool(server, TOOL_NAMES.
|
|
86
|
-
title: "
|
|
78
|
+
registerSuiMcpTool(server, TOOL_NAMES.actionCreateProposalReview, {
|
|
79
|
+
title: "Create external proposal review",
|
|
87
80
|
description: "Create a local non-signable review session from an untrusted external Sui proposal.",
|
|
88
81
|
inputSchema: z.object({
|
|
89
82
|
proposal: externalProposalSchema
|
|
@@ -283,7 +283,7 @@ const deepbookQuoteQuantitySemanticsSchema = z.object({
|
|
|
283
283
|
canUseForPaymentAnswer: z.literal(false),
|
|
284
284
|
canUseForShortfallAnswer: z.literal(false),
|
|
285
285
|
doNotCombineWithPaymentAnswer: z.literal(true),
|
|
286
|
-
requiredPaymentAnswerTool: z.literal("
|
|
286
|
+
requiredPaymentAnswerTool: z.literal("read_preview_intent_evidence"),
|
|
287
287
|
paymentAnswerUseBlockedReason: z.literal("quote_output_is_price_reference_not_payment_answer"),
|
|
288
288
|
requiredPaymentAnswerField: z.literal("responseSummary"),
|
|
289
289
|
fiatUsdCashOutAvailable: z.literal(false),
|
|
@@ -4,8 +4,8 @@ import { registerServerStatusTools, SUPPORTED_PROTOCOLS } from "./serverStatusTo
|
|
|
4
4
|
import { registerTransactionActivityTools } from "./transactionActivityTools.js";
|
|
5
5
|
import { registerWalletReadTools } from "./walletReadTools.js";
|
|
6
6
|
export { SUPPORTED_PROTOCOLS };
|
|
7
|
-
export function registerReadTools(server, deps) {
|
|
8
|
-
registerServerStatusTools(server);
|
|
7
|
+
export function registerReadTools(server, deps, registeredPromptNames) {
|
|
8
|
+
registerServerStatusTools(server, registeredPromptNames);
|
|
9
9
|
registerDeepbookReadTools(server, deps);
|
|
10
10
|
registerWalletReadTools(server, deps);
|
|
11
11
|
registerReviewActivityListTool(server, deps);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CONNECTION_RECONCILIATION_MESSAGE } from "../../../core/session/walletConnection.js";
|
|
2
2
|
import { ReadServiceCacheError, ReadServiceInputError } from "../../../core/read/readService.js";
|
|
3
3
|
import { parseSuiAddress } from "../../../core/suiAddress.js";
|
|
4
4
|
import { errorToolResult } from "../../result.js";
|
|
@@ -51,16 +51,18 @@ export async function resolveExplicitOrActiveAccount(input, deps) {
|
|
|
51
51
|
details: { ...(availability.status === "unavailable" ? { reason: availability.reason } : {}), message: availability.message, walletAvailability: availability } }) };
|
|
52
52
|
return { status: "error", result: errorToolResult({ kind: active ? "input_invalid" : "active_account_not_set",
|
|
53
53
|
details: { reason: "connected_account_required",
|
|
54
|
-
message: context?.connectionReconciliationRequired ? CONNECTION_RECONCILIATION_MESSAGE
|
|
55
|
-
|
|
54
|
+
message: context?.connectionReconciliationRequired ? CONNECTION_RECONCILIATION_MESSAGE
|
|
55
|
+
: context?.assetReadAccount.status === "address_required" && context.assetReadAccount.reason === "read_address_cleared"
|
|
56
|
+
? "The saved read address was cleared in Settings. The wallet connection and transaction permissions were not changed. This tool requires a saved Sui read address with a usable connection and does not accept an address input."
|
|
57
|
+
: "This tool requires a current Sui address with a usable wallet connection. An address alone cannot be used.",
|
|
56
58
|
...(context?.connectionReconciliationRequired ? { connectionReconciliationRequired: true } : {}),
|
|
57
59
|
followUp: { tool: TOOL_NAMES.sessionGetInteractionStatus,
|
|
58
|
-
answerFields: ["walletAvailability", "
|
|
59
|
-
reason: `Check current
|
|
60
|
+
answerFields: ["walletAvailability", "connection", "pendingWalletConnections", "assetReadAccount"],
|
|
61
|
+
reason: `Check the current connection and pending operations. Use pendingWalletConnections.items[].cardId with ${TOOL_NAMES.sessionGetWalletConnectionCard} or ${TOOL_NAMES.sessionWaitWalletConnectionCard}. If no operation is pending and the user requests connection, open ${TOOL_NAMES.sessionOpenWalletConnectionCard}. Only the user may act in that card.` } } }) };
|
|
60
62
|
}
|
|
61
|
-
const message = context?.connectionReconciliationRequired ? CONNECTION_RECONCILIATION_MESSAGE + " Provide a Sui address in chat for this public read." :
|
|
63
|
+
const message = context?.connectionReconciliationRequired ? CONNECTION_RECONCILIATION_MESSAGE + " Provide a Sui address in chat for this public read." : availability.status !== "available"
|
|
62
64
|
? "The wallet connection cannot be checked. Please provide a Sui address in chat to view its assets."
|
|
63
|
-
: "No
|
|
65
|
+
: "No usable saved Sui read address is available. Please provide a Sui address in chat.";
|
|
64
66
|
return { status: "address_required", message, result: errorToolResult({ kind: "input_invalid",
|
|
65
67
|
details: { field: "account", reason: "address_required", message, walletAvailability: availability } }) };
|
|
66
68
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { noParamsInputSchema, successOutputSchema } from "../../schemas.js";
|
|
3
3
|
import { okToolResult } from "../../result.js";
|
|
4
|
-
import { MCP_PROMPTS } from "../../prompts.js";
|
|
5
4
|
import { MCP_RESOURCES } from "../../resources.js";
|
|
6
5
|
import { EVIDENCE_POLICY, FAIL_CLOSED_TOOLS, IMPLEMENTED_TOOLS, PACKAGE_NAME, SERVER_LIMITATIONS, SERVER_NAME, SERVER_NETWORK, SERVER_RUNTIME, SERVER_TRANSPORT, SERVER_VERSION } from "../../serverInfo.js";
|
|
7
6
|
import { TOOL_NAMES } from "../../toolNames.js";
|
|
@@ -9,7 +8,7 @@ export const SUPPORTED_PROTOCOLS = [
|
|
|
9
8
|
{ id: "deepbook-v3", status: "mainnet", support: "read_and_local_review" },
|
|
10
9
|
{ id: "deepbook-margin", status: "mainnet", support: "protocol_notes_only" }
|
|
11
10
|
];
|
|
12
|
-
export function registerServerStatusTools(server) {
|
|
11
|
+
export function registerServerStatusTools(server, registeredPromptNames) {
|
|
13
12
|
server.registerTool(TOOL_NAMES.readGetServerStatus, {
|
|
14
13
|
title: "Get server status",
|
|
15
14
|
description: "Return package, runtime, tool, resource, and prompt status.",
|
|
@@ -45,7 +44,7 @@ export function registerServerStatusTools(server) {
|
|
|
45
44
|
count: z.number().int().nonnegative(),
|
|
46
45
|
names: z.array(z.string())
|
|
47
46
|
}),
|
|
48
|
-
protocolsTool: z.literal("
|
|
47
|
+
protocolsTool: z.literal("read_list_supported_protocols"),
|
|
49
48
|
limitations: z.array(z.string())
|
|
50
49
|
}),
|
|
51
50
|
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
@@ -75,8 +74,8 @@ export function registerServerStatusTools(server) {
|
|
|
75
74
|
}))
|
|
76
75
|
},
|
|
77
76
|
prompts: {
|
|
78
|
-
count:
|
|
79
|
-
names:
|
|
77
|
+
count: registeredPromptNames.length,
|
|
78
|
+
names: [...registeredPromptNames]
|
|
80
79
|
},
|
|
81
80
|
protocolsTool: TOOL_NAMES.readListSupportedProtocols,
|
|
82
81
|
limitations: [...SERVER_LIMITATIONS]
|
|
@@ -171,7 +171,7 @@ const suiTransactionAuditFactSchema = z.object({
|
|
|
171
171
|
requestedAccountEffect: transactionAccountEffectsSchema.optional(),
|
|
172
172
|
transactionContext: requestedAccountTransactionContextSchema.optional(),
|
|
173
173
|
detailLookup: z.object({
|
|
174
|
-
tool: z.literal("
|
|
174
|
+
tool: z.literal("read_inspect_sui_transaction"),
|
|
175
175
|
digest: z.string()
|
|
176
176
|
})
|
|
177
177
|
});
|
|
@@ -194,7 +194,7 @@ const requestedAccountTransactionFactSchema = z.object({
|
|
|
194
194
|
requestedAccountEffect: transactionAccountEffectsSchema,
|
|
195
195
|
transactionContext: requestedAccountTransactionContextSchema.optional(),
|
|
196
196
|
detailLookup: z.object({
|
|
197
|
-
tool: z.literal("
|
|
197
|
+
tool: z.literal("read_inspect_sui_transaction"),
|
|
198
198
|
digest: z.string()
|
|
199
199
|
})
|
|
200
200
|
});
|
|
@@ -331,7 +331,7 @@ const externalActivityTransactionRecordSchema = z.object({
|
|
|
331
331
|
compact: externalActivityTransactionCompactFactsSchema.optional(),
|
|
332
332
|
details: externalActivityTransactionDetailSchema.optional(),
|
|
333
333
|
detailLookup: z.object({
|
|
334
|
-
tool: z.literal("
|
|
334
|
+
tool: z.literal("read_inspect_sui_transaction"),
|
|
335
335
|
digest: z.string()
|
|
336
336
|
}).optional()
|
|
337
337
|
});
|
|
@@ -20,7 +20,7 @@ export function registerExecutionResultTools(server, deps) {
|
|
|
20
20
|
if (!state)
|
|
21
21
|
return errorToolResult({ kind: "session_not_found", details: { reviewSessionId } });
|
|
22
22
|
const request = state.request;
|
|
23
|
-
return okToolResult({ ...reviewStatusResponse(state), userAnswerUse: executionResultUserAnswerUse({
|
|
23
|
+
return okToolResult({ ...reviewStatusResponse(state), userAnswerUse: executionResultUserAnswerUse({ reconciliationRequired: !!state.connectionReconciliationRequired, hasRequest: !!request, hasExecutionResult: !!request?.execution }) });
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
26
|
return sessionStoreToolError(error, deps.logger);
|
|
@@ -35,7 +35,7 @@ export function registerExecutionResultTools(server, deps) {
|
|
|
35
35
|
try {
|
|
36
36
|
const result = await waitForExecutionResult((id) => readCurrentReview(deps, id), reviewSessionId, { timeoutMs, signal: extra.mcpReq.signal });
|
|
37
37
|
return okToolResult({ waitOutcome: result.waitOutcome, ...reviewStatusResponse(result),
|
|
38
|
-
userAnswerUse: executionResultUserAnswerUse({
|
|
38
|
+
userAnswerUse: executionResultUserAnswerUse({ reconciliationRequired: !!result.connectionReconciliationRequired, hasRequest: !!result.request, hasExecutionResult: !!result.request?.execution, hasWaitOutcome: true }) });
|
|
39
39
|
}
|
|
40
40
|
catch (error) {
|
|
41
41
|
return sessionStoreToolError(error, deps.logger);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { walletObservationSchema } from "../../../core/session/walletRuntime.js";
|
|
2
|
-
import { walletAvailabilitySchema, workflowProgressSchema, walletUnavailable
|
|
2
|
+
import { walletAvailabilitySchema, workflowProgressSchema, walletUnavailable } from "../../../core/session/walletConnection.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { actionPlanSchema, executionPollingStatusSchema, internalSessionStatusSchema, reviewStateOutputSchema } from "../../../core/action/schemas.js";
|
|
5
5
|
import { EXECUTION_STATUS_CATEGORIES } from "../../../core/session/status.js";
|
|
@@ -16,7 +16,7 @@ export const timeoutInputSchema = z.number().int().min(1).max(MAX_WAIT_TIMEOUT_M
|
|
|
16
16
|
export function waitExecutionInputSchema() { return { reviewSessionId: z.string().min(1), timeoutMs: timeoutInputSchema }; }
|
|
17
17
|
export const reviewStatusResponseShape = {
|
|
18
18
|
connectionReconciliationRequired: z.literal(true).optional(),
|
|
19
|
-
|
|
19
|
+
walletAvailability: walletAvailabilitySchema, walletObservation: walletObservationSchema.optional(), progress: workflowProgressSchema,
|
|
20
20
|
reviewSessionId: z.string(), status: internalSessionStatusSchema, reviewRevision: z.number().int().nonnegative(),
|
|
21
21
|
account: z.string().optional(), plans: z.array(actionPlanSchema), reviewState: reviewStateOutputSchema.optional(),
|
|
22
22
|
pollingStatus: executionPollingStatusSchema, statusCategory: executionStatusCategorySchema(), pollingHint: executionPollingHintSchema(),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { walletChainsSchema } from "../../../core/session/chainAccounts.js";
|
|
2
|
+
import { walletAvailabilitySchema, workflowProgressSchema, walletUnavailable } from "../../../core/session/walletConnection.js";
|
|
2
3
|
import { walletObservationSchema } from "../../../core/session/walletRuntime.js";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { activeAccountResponse, activeAccountResponseSchema } from "../../activeAccountResponse.js";
|
|
@@ -11,17 +12,18 @@ import { userAnswerUseSchema } from "../read/commonSchemas.js";
|
|
|
11
12
|
import { isReviewInteractionPending, reviewStatusResponse } from "../../../core/session/status.js";
|
|
12
13
|
import { latest, reviewStatusResponseShape, readCurrentReview } from "./shared.js";
|
|
13
14
|
import { pendingConnectionStatusSchema, connectionViewSchema, assetReadAccountSchema } from "../../../core/session/workflowView.js";
|
|
15
|
+
import { pendingWalletConnectionOperationSchema } from "../../../core/session/walletConnectionOperations.js";
|
|
14
16
|
export function registerSessionStatusTools(server, deps) {
|
|
15
17
|
server.registerTool(TOOL_NAMES.sessionGetInteractionStatus, {
|
|
16
|
-
title: "Get local interaction status", description: "Read wallet
|
|
18
|
+
title: "Get local interaction status", description: "Read the current wallet connection, asset read account, and pending interactions.",
|
|
17
19
|
inputSchema: noParamsInputSchema,
|
|
18
20
|
outputSchema: successOutputSchema({ walletAvailability: walletAvailabilitySchema, walletObservation: walletObservationSchema.optional(), activeAccount: activeAccountResponseSchema,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
requestedChains: walletChainsSchema,
|
|
22
|
+
connection: connectionViewSchema.nullable(), pendingOperation: pendingWalletConnectionOperationSchema.optional(), assetReadAccount: assetReadAccountSchema,
|
|
23
|
+
canDisconnect: z.boolean(), connectionReconciliationRequired: z.literal(true).optional(),
|
|
22
24
|
pendingWalletConnections: z.object({ limit: z.number().int().positive(), truncated: z.boolean(),
|
|
23
25
|
items: z.array(z.object({ cardId: z.string(), connectionId: z.string().optional(),
|
|
24
|
-
status: pendingConnectionStatusSchema, progress: workflowProgressSchema, lastActivityAt: z.string() })) }),
|
|
26
|
+
operationId: z.string().uuid(), status: pendingConnectionStatusSchema, progress: workflowProgressSchema, lastActivityAt: z.string() })) }),
|
|
25
27
|
pendingReviewSessions: z.object({ limit: z.number().int().positive(), truncated: z.boolean(), items: z.array(z.object(reviewStatusResponseShape)) }),
|
|
26
28
|
userAnswerUse: userAnswerUseSchema }),
|
|
27
29
|
annotations: { readOnlyHint: false, openWorldHint: false }
|
|
@@ -34,14 +36,14 @@ export function registerSessionStatusTools(server, deps) {
|
|
|
34
36
|
return activityStoreToolError(error, deps.logger);
|
|
35
37
|
}
|
|
36
38
|
try {
|
|
37
|
-
const context = deps.workflow?.reconcileConnectionContext() ?? {
|
|
39
|
+
const context = deps.workflow?.reconcileConnectionContext() ?? { requestedChains: [], canDisconnect: false,
|
|
38
40
|
assetReadAccount: { status: "address_required" }, walletAvailability: walletUnavailable("initialization_failed") };
|
|
39
41
|
const connections = deps.workflow?.pendingConnections() ?? [];
|
|
40
42
|
const states = await Promise.all(deps.sessions.reviewSessionIds().map((id) => readCurrentReview(deps, id)));
|
|
41
43
|
const reviews = states.flatMap((state) => state && isReviewInteractionPending(state) ? [reviewStatusResponse(state)] : []);
|
|
42
44
|
return okToolResult({ activeAccount: activeAccountResponse(active), pendingWalletConnections: latest(connections),
|
|
43
|
-
pendingReviewSessions: latest(reviews), ...context,
|
|
44
|
-
userAnswerUse: interactionStatusUserAnswerUse("walletObservation" in context && context.walletObservation !== undefined, "
|
|
45
|
+
pendingReviewSessions: latest(reviews), ...context, connection: "connection" in context ? context.connection ?? null : null,
|
|
46
|
+
userAnswerUse: interactionStatusUserAnswerUse("walletObservation" in context && context.walletObservation !== undefined, "connectionReconciliationRequired" in context && !!context.connectionReconciliationRequired) });
|
|
45
47
|
}
|
|
46
48
|
catch (error) {
|
|
47
49
|
return sessionStoreToolError(error, deps.logger);
|
|
@@ -59,7 +61,7 @@ export function registerSessionStatusTools(server, deps) {
|
|
|
59
61
|
return errorToolResult({ kind: "session_not_found", details: { reviewSessionId } });
|
|
60
62
|
const session = state.session;
|
|
61
63
|
return okToolResult({ ...reviewStatusResponse(state),
|
|
62
|
-
userAnswerUse: reviewStatusUserAnswerUse(!!session.reviewState, !!session.reviewState?.adapterLifecycle, !!session.reviewState?.humanReadableReview, !!session.reviewState?.simulation, !!state.
|
|
64
|
+
userAnswerUse: reviewStatusUserAnswerUse(!!session.reviewState, !!session.reviewState?.adapterLifecycle, !!session.reviewState?.humanReadableReview, !!session.reviewState?.simulation, !!state.connectionReconciliationRequired) });
|
|
63
65
|
}
|
|
64
66
|
catch (error) {
|
|
65
67
|
return sessionStoreToolError(error, deps.logger);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { walletAvailabilitySchema } from "../../../core/session/walletConnection.js";
|
|
2
|
+
import { walletConnectionOperationSchema } from "../../../core/session/walletConnectionOperations.js";
|
|
3
|
+
import { walletConnectionCardInputSchema } from "../../../core/session/walletConnectionOperations.js";
|
|
1
4
|
import { z } from "zod";
|
|
2
5
|
import { cardMetadata, createWorkflowCard } from "../../../mcp-ui/tools.js";
|
|
3
6
|
import { cardSnapshotSchema } from "../../../mcp-ui/contracts.js";
|
|
@@ -10,44 +13,53 @@ import { CardError } from "../../../core/session/cardSessionStore.js";
|
|
|
10
13
|
import { sessionStoreToolError } from "../../toolErrors.js";
|
|
11
14
|
export function registerWalletConnectionTools(server, deps) {
|
|
12
15
|
const failure = (error) => sessionStoreToolError(error, deps.logger);
|
|
13
|
-
server.registerTool(TOOL_NAMES.
|
|
14
|
-
title: "
|
|
15
|
-
inputSchema:
|
|
16
|
+
server.registerTool(TOOL_NAMES.sessionOpenWalletConnectionCard, {
|
|
17
|
+
title: "Connect wallet", description: "Open a card for one wallet connection request.",
|
|
18
|
+
inputSchema: walletConnectionCardInputSchema, outputSchema: successOutputSchema(cardSnapshotSchema.shape),
|
|
16
19
|
_meta: cardMetadata("connect"), annotations: { readOnlyHint: false, openWorldHint: false }
|
|
17
|
-
}, async (
|
|
18
|
-
return await createWorkflowCard(server, deps, "connect",
|
|
20
|
+
}, async (input) => { try {
|
|
21
|
+
return await createWorkflowCard(server, deps, "connect", input);
|
|
19
22
|
}
|
|
20
23
|
catch (error) {
|
|
21
24
|
return failure(error);
|
|
22
25
|
} });
|
|
23
|
-
server.registerTool(TOOL_NAMES.
|
|
24
|
-
title: "
|
|
25
|
-
inputSchema:
|
|
26
|
+
server.registerTool(TOOL_NAMES.sessionOpenWalletDisconnectionCard, {
|
|
27
|
+
title: "Disconnect wallet", description: "Open a confirmation card for the current wallet disconnection.",
|
|
28
|
+
inputSchema: walletConnectionCardInputSchema, outputSchema: successOutputSchema(cardSnapshotSchema.shape),
|
|
29
|
+
_meta: cardMetadata("disconnect"), annotations: { readOnlyHint: false, openWorldHint: false }
|
|
30
|
+
}, async (input) => { try {
|
|
31
|
+
return await createWorkflowCard(server, deps, "disconnect", input);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return failure(error);
|
|
35
|
+
} });
|
|
36
|
+
const operationState = { card: cardSnapshotSchema, operation: walletConnectionOperationSchema.nullable(),
|
|
37
|
+
walletAvailability: walletAvailabilitySchema, evaluatedAt: z.string().datetime() };
|
|
38
|
+
server.registerTool(TOOL_NAMES.sessionGetWalletConnectionCard, {
|
|
39
|
+
title: "Get wallet connection card", description: "Read a wallet card and its exact operation’s current settlement.",
|
|
40
|
+
inputSchema: z.object({ cardId: z.string().min(1) }).strict(), outputSchema: successOutputSchema(operationState),
|
|
26
41
|
annotations: { readOnlyHint: false, openWorldHint: false }
|
|
27
42
|
}, async ({ cardId }) => {
|
|
28
43
|
try {
|
|
29
44
|
if (!deps.cards)
|
|
30
45
|
return failure(new CardError("Wallet card is unavailable."));
|
|
31
|
-
|
|
32
|
-
if (snapshot.kind !== "connect")
|
|
33
|
-
return failure(new CardError("Wallet card is unavailable."));
|
|
34
|
-
return okToolResult(snapshot);
|
|
46
|
+
return okToolResult(await deps.cards.store.readWalletOperation(cardId));
|
|
35
47
|
}
|
|
36
48
|
catch (error) {
|
|
37
49
|
return failure(error);
|
|
38
50
|
}
|
|
39
51
|
});
|
|
40
|
-
server.registerTool(TOOL_NAMES.
|
|
41
|
-
title: "Wait for wallet connection", description: "Wait briefly for
|
|
42
|
-
inputSchema: z.object({ cardId: z.string().min(1), timeoutMs: timeoutInputSchema }),
|
|
43
|
-
outputSchema: successOutputSchema({ waitOutcome: z.enum(WAIT_OUTCOMES)
|
|
52
|
+
server.registerTool(TOOL_NAMES.sessionWaitWalletConnectionCard, {
|
|
53
|
+
title: "Wait for wallet connection card", description: "Wait briefly for one wallet card's exact operation and cleanup.",
|
|
54
|
+
inputSchema: z.object({ cardId: z.string().min(1), timeoutMs: timeoutInputSchema }).strict(),
|
|
55
|
+
outputSchema: successOutputSchema({ ...operationState, waitOutcome: z.enum(WAIT_OUTCOMES) }),
|
|
44
56
|
annotations: { readOnlyHint: false, openWorldHint: false }
|
|
45
57
|
}, async ({ cardId, timeoutMs }, extra) => {
|
|
46
58
|
try {
|
|
47
59
|
if (!deps.cards)
|
|
48
60
|
return failure(new CardError("Wallet card is unavailable."));
|
|
49
61
|
const result = await waitForWalletConnection(deps.cards.store, cardId, { timeoutMs, signal: extra.mcpReq.signal });
|
|
50
|
-
return okToolResult(
|
|
62
|
+
return okToolResult(result);
|
|
51
63
|
}
|
|
52
64
|
catch (error) {
|
|
53
65
|
return failure(error);
|