@zktx.io/sui-mcp 0.7.0 → 0.8.1

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.
Files changed (71) hide show
  1. package/README.md +89 -42
  2. package/dist/core/activity/localDataService.js +8 -21
  3. package/dist/core/activity/localDataValidation.js +22 -46
  4. package/dist/core/activity/sqliteAccountStore.js +46 -0
  5. package/dist/core/activity/sqliteActivityStore.js +65 -147
  6. package/dist/core/activity/sqliteActivityStoreSchema.js +44 -28
  7. package/dist/core/activity/sqliteActivityStoreTypes.js +9 -0
  8. package/dist/core/activity/transactionActivityService.js +2 -2
  9. package/dist/core/preferences/preferencesStore.js +2 -2
  10. package/dist/core/preferences/sqlitePreferencesRepository.js +10 -0
  11. package/dist/core/session/cardResult.js +41 -0
  12. package/dist/core/session/cardSession.js +1 -1
  13. package/dist/core/session/cardSessionStore.js +51 -19
  14. package/dist/core/session/chainAccounts.js +120 -0
  15. package/dist/core/session/sessionStore.js +4 -8
  16. package/dist/core/session/settingsFileStore.js +3 -30
  17. package/dist/core/session/settingsOperation.js +27 -19
  18. package/dist/core/session/settingsWorkflow.js +161 -87
  19. package/dist/core/session/sqliteCardStore.js +34 -14
  20. package/dist/core/session/sqliteSessionStore.js +5 -5
  21. package/dist/core/session/sqliteSettingsWorkflowStore.js +135 -41
  22. package/dist/core/session/sqliteTransactionRequest.js +18 -0
  23. package/dist/core/session/sqliteWalletConnectionOperation.js +13 -0
  24. package/dist/core/session/sqliteWalletWorkflowStore.js +569 -333
  25. package/dist/core/session/status.js +2 -2
  26. package/dist/core/session/wait.js +6 -11
  27. package/dist/core/session/walletConnection.js +71 -46
  28. package/dist/core/session/walletConnectionOperations.js +24 -0
  29. package/dist/core/session/walletRuntime.js +7 -13
  30. package/dist/core/session/walletWorkflow.js +248 -99
  31. package/dist/core/session/workflowState.js +104 -38
  32. package/dist/core/session/workflowView.js +92 -101
  33. package/dist/mcp/activeAccountResponse.js +3 -0
  34. package/dist/mcp/responseGuidance.js +7 -9
  35. package/dist/mcp/serverInfo.js +11 -10
  36. package/dist/mcp/toolErrors.js +5 -3
  37. package/dist/mcp/toolNames.js +1 -0
  38. package/dist/mcp/tools/action/prepareSuiActionReview.js +9 -16
  39. package/dist/mcp/tools/read/readToolHelpers.js +9 -7
  40. package/dist/mcp/tools/session/executionResultTools.js +2 -2
  41. package/dist/mcp/tools/session/shared.js +2 -2
  42. package/dist/mcp/tools/session/statusTools.js +12 -10
  43. package/dist/mcp/tools/session/walletConnectionTools.js +26 -14
  44. package/dist/mcp/tools/settings/index.js +7 -4
  45. package/dist/mcp-app/account.html +7 -7
  46. package/dist/mcp-app/chart.html +3 -3
  47. package/dist/mcp-app/connect.html +13 -13
  48. package/dist/mcp-app/disconnect.html +3637 -0
  49. package/dist/mcp-app/disconnect.notices.txt +1480 -0
  50. package/dist/mcp-app/receipt.html +393 -393
  51. package/dist/mcp-app/review.html +459 -459
  52. package/dist/mcp-app/settings.html +7 -7
  53. package/dist/mcp-ui/contracts.js +3 -1
  54. package/dist/mcp-ui/tools.js +4 -4
  55. package/dist/runtime/application.js +1 -1
  56. package/dist/runtime/localSettingsService.js +7 -4
  57. package/dist/runtime/runtimeTermination.js +3 -0
  58. package/dist/runtime/smokeMainnetRead.js +5 -4
  59. package/dist/runtime/walletConnectTransport.js +16 -16
  60. package/dist/runtime/walletSdkChildRuntime.js +29 -12
  61. package/dist/runtime/walletSdkIpc.js +5 -4
  62. package/dist/runtime/walletSdkProcess.js +24 -8
  63. package/docs/AGENT_BEHAVIOR.md +82 -54
  64. package/docs/LOCAL_DB_ARCHITECTURE.md +100 -70
  65. package/docs/MCP_SETUP.md +384 -347
  66. package/docs/MCP_TOOLS.md +292 -177
  67. package/docs/SDK_API.md +15 -6
  68. package/docs/TRANSACTION_ACTIVITY_LOG.md +4 -0
  69. package/docs/UTILITY_INDEX.md +9 -7
  70. package/docs/WALLET_CONNECTION.md +162 -167
  71. package/package.json +1 -1
@@ -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: { reason: error.reason, message: error.message } });
51
- if (error instanceof WorkflowConflict || error instanceof CardError) {
52
- return errorToolResult({ kind: "input_invalid", details: { reason: error.message } });
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({
@@ -37,6 +37,7 @@ export const TOOL_NAMES = {
37
37
  settingsGetLocalSettings: "settings_get_local_settings",
38
38
  actionStartReview: "action_start_review",
39
39
  actionCreateProposalReview: "action_create_proposal_review",
40
+ sessionOpenWalletDisconnectionCard: "session_open_wallet_disconnection_card",
40
41
  sessionOpenWalletConnectionCard: "session_open_wallet_connection_card",
41
42
  sessionGetWalletConnectionCard: "session_get_wallet_connection_card",
42
43
  sessionWaitWalletConnectionCard: "session_wait_wallet_connection_card",
@@ -9,7 +9,7 @@ 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 { activityStoreToolError, sessionStoreToolError } from "../../toolErrors.js";
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) {
@@ -18,7 +18,7 @@ export function registerActionTools(server, deps) {
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,7 +69,7 @@ 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);
@@ -1,4 +1,4 @@
1
- import { CONNECTION_CONFLICT_MESSAGE, CONNECTION_RECONCILIATION_MESSAGE } from "../../../core/session/walletConnection.js";
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 : context?.connectionConflict ? CONNECTION_CONFLICT_MESSAGE : "This tool requires a selected account with a usable wallet connection. An address alone cannot be used.",
55
- ...(context?.connectionConflict ? { connectionConflict: context.connectionConflict } : {}),
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", "connections", "pendingWalletConnections", "assetReadAccount"],
59
- reason: `Check current connections 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 or account selection, open ${TOOL_NAMES.sessionOpenWalletConnectionCard}. Only the user may act in that card.` } } }) };
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." : context?.connectionConflict ? CONNECTION_CONFLICT_MESSAGE + " Provide a Sui address in chat for this public read." : availability.status !== "available"
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 connected wallet is available for the selected account. Please provide a Sui address in chat.";
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
  }
@@ -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({ hasConnectionConflict: !!state.connectionConflict, reconciliationRequired: !!state.connectionReconciliationRequired, hasRequest: !!request, hasExecutionResult: !!request?.execution }) });
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({ hasConnectionConflict: !!result.connectionConflict, reconciliationRequired: !!result.connectionReconciliationRequired, hasRequest: !!result.request, hasExecutionResult: !!result.request?.execution, hasWaitOutcome: true }) });
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, connectionConflictSchema } from "../../../core/session/walletConnection.js";
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
- connectionConflict: connectionConflictSchema.optional(), walletAvailability: walletAvailabilitySchema, walletObservation: walletObservationSchema.optional(), progress: workflowProgressSchema,
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 { walletAvailabilitySchema, workflowProgressSchema, walletUnavailable, connectionConflictSchema } from "../../../core/session/walletConnection.js";
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 connections, the default asset account, and pending interactions.",
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
- connections: z.array(connectionViewSchema), assetReadAccount: assetReadAccountSchema,
20
- connectionConflict: connectionConflictSchema.optional(),
21
- manageableConnectionIds: z.array(z.string().min(1)), connectionReconciliationRequired: z.literal(true).optional(),
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() ?? { connections: [], manageableConnectionIds: [],
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, "connectionConflict" in context && !!context.connectionConflict, "connectionReconciliationRequired" in context && !!context.connectionReconciliationRequired) });
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.connectionConflict, !!state.connectionReconciliationRequired) });
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";
@@ -11,43 +14,52 @@ import { sessionStoreToolError } from "../../toolErrors.js";
11
14
  export function registerWalletConnectionTools(server, deps) {
12
15
  const failure = (error) => sessionStoreToolError(error, deps.logger);
13
16
  server.registerTool(TOOL_NAMES.sessionOpenWalletConnectionCard, {
14
- title: "Open wallet connection controls", description: "Open a card for Sui wallet connection, disconnection and account selection.",
15
- inputSchema: z.object({ intent: z.enum(["manage", "connect", "disconnect"]).default("manage") }), outputSchema: successOutputSchema(cardSnapshotSchema.shape),
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 ({ intent }) => { try {
18
- return await createWorkflowCard(server, deps, "connect", { intent });
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
  } });
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() };
23
38
  server.registerTool(TOOL_NAMES.sessionGetWalletConnectionCard, {
24
- title: "Get wallet connection card", description: "Read the saved state of one wallet connection card.",
25
- inputSchema: z.object({ cardId: z.string().min(1) }), outputSchema: successOutputSchema(cardSnapshotSchema.shape),
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
- const snapshot = await deps.cards.store.readSaved(cardId);
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
52
  server.registerTool(TOOL_NAMES.sessionWaitWalletConnectionCard, {
41
- title: "Wait for wallet connection card", description: "Wait briefly for a wallet connection card's approval or required user input.",
42
- inputSchema: z.object({ cardId: z.string().min(1), timeoutMs: timeoutInputSchema }),
43
- outputSchema: successOutputSchema({ waitOutcome: z.enum(WAIT_OUTCOMES), card: cardSnapshotSchema }),
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({ waitOutcome: result.waitOutcome, card: result.snapshot });
62
+ return okToolResult(result);
51
63
  }
52
64
  catch (error) {
53
65
  return failure(error);
@@ -1,3 +1,5 @@
1
+ import { settingsCardInputSchema } from "../../../core/session/settingsOperation.js";
2
+ import { walletChainsSchema } from "../../../core/session/chainAccounts.js";
1
3
  import { z } from "zod";
2
4
  import { SETTINGS_APPLIES_AFTER_RESTART } from "../../../core/preferences/preferencesStore.js";
3
5
  import { registerSuiMcpTool } from "../../registerTool.js";
@@ -16,11 +18,11 @@ const endpointSettingSchema = z.object({
16
18
  appliesAfter: z.literal(SETTINGS_APPLIES_AFTER_RESTART).optional()
17
19
  });
18
20
  export function registerSettingsTools(server, deps) {
19
- registerAppTool(server, TOOL_NAMES.settingsCreateLocalSettingsSession, { title: "Settings", description: "Open a local settings card.", inputSchema: noParamsInputSchema,
21
+ registerAppTool(server, TOOL_NAMES.settingsCreateLocalSettingsSession, { title: "Settings", description: "Open local settings, read a recorded operation, or request delivery of an existing backup.", inputSchema: settingsCardInputSchema,
20
22
  outputSchema: successOutputSchema(cardSnapshotSchema.shape), _meta: cardMetadata("settings"),
21
- annotations: { readOnlyHint: false, openWorldHint: false } }, async () => {
23
+ annotations: { readOnlyHint: false, openWorldHint: false } }, async (input) => {
22
24
  try {
23
- return await createWorkflowCard(server, deps, "settings", {});
25
+ return await createWorkflowCard(server, deps, "settings", input);
24
26
  }
25
27
  catch (error) {
26
28
  return sessionStoreToolError(error, deps.logger);
@@ -32,7 +34,8 @@ export function registerSettingsTools(server, deps) {
32
34
  inputSchema: noParamsInputSchema,
33
35
  outputSchema: successOutputSchema({
34
36
  suiGrpcUrl: endpointSettingSchema,
35
- suiGraphqlUrl: endpointSettingSchema
37
+ suiGraphqlUrl: endpointSettingSchema,
38
+ walletConnectionChains: walletChainsSchema
36
39
  }),
37
40
  annotations: { readOnlyHint: true, openWorldHint: false }
38
41
  }, async () => {