@wowok/agent-mcp 2.2.8

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 (62) hide show
  1. package/README.md +56 -0
  2. package/dist/index.d.ts +15800 -0
  3. package/dist/index.js +1479 -0
  4. package/dist/schema/call/allocation.d.ts +1430 -0
  5. package/dist/schema/call/allocation.js +24 -0
  6. package/dist/schema/call/arbitration.d.ts +1974 -0
  7. package/dist/schema/call/arbitration.js +92 -0
  8. package/dist/schema/call/base.d.ts +7325 -0
  9. package/dist/schema/call/base.js +138 -0
  10. package/dist/schema/call/contact.d.ts +970 -0
  11. package/dist/schema/call/contact.js +37 -0
  12. package/dist/schema/call/demand.d.ts +1265 -0
  13. package/dist/schema/call/demand.js +47 -0
  14. package/dist/schema/call/guard.d.ts +951 -0
  15. package/dist/schema/call/guard.js +58 -0
  16. package/dist/schema/call/handler.d.ts +38 -0
  17. package/dist/schema/call/handler.js +171 -0
  18. package/dist/schema/call/index.d.ts +18 -0
  19. package/dist/schema/call/index.js +18 -0
  20. package/dist/schema/call/machine.d.ts +3974 -0
  21. package/dist/schema/call/machine.js +152 -0
  22. package/dist/schema/call/order.d.ts +974 -0
  23. package/dist/schema/call/order.js +34 -0
  24. package/dist/schema/call/payment.d.ts +404 -0
  25. package/dist/schema/call/payment.js +17 -0
  26. package/dist/schema/call/permission.d.ts +3017 -0
  27. package/dist/schema/call/permission.js +105 -0
  28. package/dist/schema/call/personal.d.ts +1472 -0
  29. package/dist/schema/call/personal.js +68 -0
  30. package/dist/schema/call/progress.d.ts +725 -0
  31. package/dist/schema/call/progress.js +26 -0
  32. package/dist/schema/call/proof.d.ts +320 -0
  33. package/dist/schema/call/proof.js +27 -0
  34. package/dist/schema/call/repository.d.ts +2358 -0
  35. package/dist/schema/call/repository.js +76 -0
  36. package/dist/schema/call/reward.d.ts +1232 -0
  37. package/dist/schema/call/reward.js +30 -0
  38. package/dist/schema/call/service.d.ts +3494 -0
  39. package/dist/schema/call/service.js +82 -0
  40. package/dist/schema/call/treasury.d.ts +2345 -0
  41. package/dist/schema/call/treasury.js +71 -0
  42. package/dist/schema/common/index.d.ts +843 -0
  43. package/dist/schema/common/index.js +347 -0
  44. package/dist/schema/index.d.ts +7 -0
  45. package/dist/schema/index.js +7 -0
  46. package/dist/schema/local/index.d.ts +17522 -0
  47. package/dist/schema/local/index.js +855 -0
  48. package/dist/schema/local/wip.d.ts +784 -0
  49. package/dist/schema/local/wip.js +187 -0
  50. package/dist/schema/messenger/index.d.ts +4655 -0
  51. package/dist/schema/messenger/index.js +446 -0
  52. package/dist/schema/query/index.d.ts +73445 -0
  53. package/dist/schema/query/index.js +1324 -0
  54. package/dist/schema/utils/guard-parser.d.ts +20 -0
  55. package/dist/schema/utils/guard-parser.js +401 -0
  56. package/dist/schema/utils/guard-query-utils.d.ts +5 -0
  57. package/dist/schema/utils/guard-query-utils.js +22 -0
  58. package/dist/schema/utils/node-parser.d.ts +45 -0
  59. package/dist/schema/utils/node-parser.js +353 -0
  60. package/dist/schema/utils/permission-index-utils.d.ts +2 -0
  61. package/dist/schema/utils/permission-index-utils.js +7 -0
  62. package/package.json +48 -0
package/dist/index.js ADDED
@@ -0,0 +1,1479 @@
1
+ #!/usr/bin/env node
2
+ import { z } from "zod";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { readFileSync } from "fs";
6
+ import { resolve } from "path";
7
+ const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
8
+ import { CallService_DataSchema, CallMachine_DataSchema, MachineNode2File_InputSchema, MachineNode2File_OutputWrappedSchema, CallProgress_DataSchema, CallPermission_DataSchema, CallGuard_DataSchema, Guard2File_InputSchema, Guard2File_OutputWrappedSchema, CallArbitration_DataSchema, CallRepository_DataSchema, CallContact_DataSchema, CallTreasury_DataSchema, CallReward_DataSchema, CallAllocation_DataSchema, CallPersonal_DataSchema, CallPayment_DataSchema, CallDemand_DataSchema, CallOrder_DataSchema, CallEnvSchema, SubmissionCallSchema, strictParse, CallOutputSchema, handleCallResult, createServerConfig, createCapabilitiesConfig, createToolMeta, transformSubmission, getEnvConfig, WipGenerationOptionsSchema, WipToHtmlOptionsSchema, TokenDataFilterSchema, LocalInfoFilterSchema, LocalMarkFilterSchema, AccountFilterSchema, TokenTypeSchema, OnchainEventsInputSchema, OnchainEventsResultSchema, ProtocolInfoQuerySchema, ProtocolInfoResultSchema, TableAnswerSchema, TableItem_RepositoryDataSchema, TableItem_PermissionPermSchema, TableItem_EntityRegistrarSchema, TableItem_EntityLinkerSchema, TableItem_RewardRecordSchema, TableItem_DemandPresenterSchema, TableItem_TreasuryHistorySchema, TableItem_MachineNodeSchema, TableItem_ProgressHistorySchema, TableItem_AddressMarkSchema, NameOrAddressSchema, ObjectBaseSchema, AccountOrMark_AddressSchema, AccountOrMark_AddressAISchema, EntrypointSchema, AccountOperationOutputWrappedSchema, LocalMarkOperationOutputWrappedSchema, LocalInfoOperationOutputWrappedSchema, WipOperationOutputSchema, MessengerOperationOutputSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, parseMachineNodesFromText, formatNodeErrors as formatMachineNodeErrors, MessengerOperationInputSchema, } from "./schema/index.js";
9
+ import { CallService, CallMachine, CallProgress, CallPermission, CallGuard, CallArbitration, CallRepository, CallContact, CallTreasury, CallReward, CallAllocation, CallPersonal, CallPayment, CallDemand, CallOrder, gen_passport, guard2file, parseGuardFile, formatGuardParseErrors, machineNode2file, generateNodeComments, generate_wip, verify_wip, sign_wip, wip2html, account_operation, local_mark_operation, local_info_operation, watch_conversations, send_message, send_file, watch_messages, extract_zip_messages, generate_wts, verify_wts, sign_wts, wts2html, proof_message, mark_messages_as_viewed, mark_conversation_as_viewed, query_local_mark_list, query_account_list, query_local_info_list, query_local_token_list, query_account, query_personal, query_objects, query_table, query_tableItem, queryProtocolInfo, query_received, queryTableItem_RepositoryData, queryTableItem_PermissionPerm, queryTableItem_RewardRecord, queryTableItem_DemandPresenter, queryTableItem_TreasuryHistory, queryTableItem_MachineNode, queryTableItem_ProgressHistory, queryTableItem_AddressMark, queryTableItem_EntityRegistrar, queryTableItem_EntityLinker, query_events, blacklist, friendslist, guardlist, settings, AmountType, } from "wowok";
10
+ const SERVER_DESCRIPTION = `WoWok MCP Server - Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.
11
+
12
+ ## Token System Overview
13
+
14
+ ### Default Platform Token: WOW
15
+ - Token Type: 0x2::wow::WOW
16
+ - Precision: 1_000_000_000 (9 decimal places)
17
+ - This is the default token for all operations unless specified otherwise
18
+
19
+ ### Multi-Token Support
20
+ The platform supports ANY token (e.g., USDT, USDC, custom tokens). To use non-WOW tokens:
21
+ 1. Use query_toolkit with query_type='token_list' to query available tokens and their precision info
22
+ 2. Use the token's full type string (e.g., '0x2::usdt::USDT') in token_type parameter
23
+ 3. Each token has its own precision - always verify before operations
24
+
25
+ ### Token Precision Handling
26
+ Different tokens have different precisions. ALWAYS query to verify:
27
+ - WOW (default): 1_000_000_000 (9 decimals)
28
+ - Other tokens: Use query_toolkit with query_type='token_list' to get actual precision
29
+ - Never assume a token's decimal places - always query first
30
+
31
+ ## CRITICAL: Token Amount Handling
32
+
33
+ ### Amount Input Rules
34
+ 1. WITH currency unit (e.g., '2WOW', '10.5WOW', '100USDT'):
35
+ - Auto-converted using token's precision: 2WOW -> 2_000_000_000
36
+ - Use for: All on-chain token operations
37
+ - MUST match the token_type parameter
38
+
39
+ 2. WITHOUT currency unit (e.g., '2', '100'):
40
+ - Used as-is: 2 -> 2
41
+ - Use for: Regular numeric parameters (counts, indices, etc.)
42
+
43
+ ### Multi-Token Operation Examples
44
+ - Create USDT-priced Service: token_type='0x2::usdt::USDT', amount='100USDT'
45
+ - Allocate USDC rewards: token_type='0x2::usdc::USDC', amount='500USDC'
46
+ - WOW remains default: omit token_type or use '0x2::wow::WOW'
47
+
48
+ ### Security Warning
49
+ Token amounts are HIGHLY SENSITIVE. Always:
50
+ - Confirm user's intent before executing transfers
51
+ - Verify token type and amount format (with/without unit)
52
+ - Query token precision if unsure
53
+ - Double-check large amount transactions
54
+ - Never assume decimal places - use explicit token unit
55
+
56
+ ## Tool Selection Guide
57
+
58
+ | User Intent | Correct Tool | Wrong Tool (Avoid) |
59
+ |------------|--------------|-------------------|
60
+ | Create service listing | onchain_operations (service) | query_toolkit |
61
+ | Send coins to address | onchain_operations (payment) | account_operation |
62
+ | Check my balance | query_toolkit (account_balance) | onchain_operations |
63
+ | Manage local wallet | account_operation | onchain_operations |
64
+ | Export Guard for edit | guard2file | query_toolkit |
65
+ | Send/Watch encrypted message | messenger_operation | onchain_operations |
66
+ | Create workflow template | onchain_operations (machine) | wip_file |
67
+ | Store my phone number | local_info_operation | onchain_operations |
68
+ | Buy service (create order) | onchain_operations (order) | onchain_operations (service) |
69
+ | Manage my orders | onchain_operations (order) | query_toolkit |
70
+ | Apply for arbitration | onchain_operations (order) | onchain_operations (arbitration) |
71
+ | Create reward pool for marketing | onchain_operations (reward) | onchain_operations (treasury) |
72
+ | Claim rewards from pool | onchain_operations (reward) | query_toolkit |
73
+ | Create fund allocation plan | onchain_operations (allocation) | onchain_operations (treasury) |
74
+ | Execute fund distribution | onchain_operations (allocation) | onchain_operations (payment) |
75
+ | Post service demand with reward | onchain_operations (demand) | onchain_operations (service) |
76
+ | Submit solution for demand | onchain_operations (demand) | onchain_operations (order) |
77
+ | Create team treasury | onchain_operations (treasury) | onchain_operations (allocation) |
78
+ | Deposit/Withdraw from treasury | onchain_operations (treasury) | onchain_operations (payment) |
79
+ | Create access control rules | onchain_operations (permission) | onchain_operations (guard) |
80
+ | Create validation rules (Guard) | onchain_operations (guard) | onchain_operations (permission) |
81
+ | Export Guard for editing | guard2file | query_toolkit |
82
+ | Export Machine nodes for editing | machineNode2file | query_toolkit |
83
+ | Query token list and precision | query_toolkit (token_list) | wowok_buildin_info |
84
+ | Watch on-chain events | onchain_events | query_toolkit |
85
+ | Generate WIP promise file | wip_file (generate) | messenger_operation |
86
+ | Sign WIP file | wip_file (sign) | account_operation (signData) |
87
+ | Verify WIP file integrity | wip_file (verify) | query_toolkit |
88
+ | Send encrypted file via messenger | messenger_operation (send_file) | wip_file |
89
+ | Generate witness timestamp (WTS) | messenger_operation (generate_wts) | wip_file |
90
+ | Query protocol constants | wowok_buildin_info | query_toolkit |
91
+ | Get documentation URL | documents_and_learn | wowok_buildin_info |
92
+
93
+ ## Local vs On-chain Operations
94
+
95
+ ### LOCAL ONLY (Never touch blockchain):
96
+ - account_operation
97
+ - local_mark_operation
98
+ - local_info_operation
99
+
100
+ ### ON-CHAIN (Blockchain transactions):
101
+ - onchain_operations
102
+ - messenger_operation (some operations)
103
+ - wip_file (sign operation)
104
+
105
+ ### QUERY (Read-only):
106
+ - query_toolkit
107
+ - onchain_events
108
+ - wowok_buildin_info
109
+ - documents_and_learn
110
+ - guard2file
111
+ - machineNode2file
112
+ `;
113
+ const server = new McpServer(createServerConfig(packageJson, SERVER_DESCRIPTION), createCapabilitiesConfig());
114
+ function convertAmountType(type) {
115
+ if (typeof type === "number")
116
+ return type;
117
+ const upperType = type.toUpperCase();
118
+ if (upperType === "GUARDU64IDENTIFIER" || upperType === "GUARD_U64_IDENTIFIER") {
119
+ return AmountType.GuardU64Identifier;
120
+ }
121
+ if (upperType === "FIXED") {
122
+ return AmountType.Fixed;
123
+ }
124
+ return AmountType.Fixed;
125
+ }
126
+ function transformRewardData(data) {
127
+ if (!data)
128
+ return data;
129
+ const transformed = { ...data };
130
+ if (transformed.guard_add && Array.isArray(transformed.guard_add)) {
131
+ transformed.guard_add = transformed.guard_add.map((guard) => {
132
+ if (guard.amount && typeof guard.amount.type === "string") {
133
+ return {
134
+ ...guard,
135
+ amount: {
136
+ ...guard.amount,
137
+ type: convertAmountType(guard.amount.type)
138
+ }
139
+ };
140
+ }
141
+ return guard;
142
+ });
143
+ }
144
+ return transformed;
145
+ }
146
+ const OnchainOperationsSchema = z.preprocess((input) => {
147
+ if (typeof input === 'object' && input !== null) {
148
+ const obj = { ...input };
149
+ if (typeof obj.description === 'string' && !obj.operation_type) {
150
+ try {
151
+ const parsed = JSON.parse(obj.description);
152
+ if (parsed && typeof parsed === 'object' && parsed.operation_type) {
153
+ return parsed;
154
+ }
155
+ }
156
+ catch { }
157
+ }
158
+ if (typeof obj.data === 'string') {
159
+ try {
160
+ obj.data = JSON.parse(obj.data);
161
+ }
162
+ catch { }
163
+ }
164
+ if (typeof obj.env === 'string') {
165
+ try {
166
+ obj.env = JSON.parse(obj.env);
167
+ }
168
+ catch { }
169
+ }
170
+ if (typeof obj.submission === 'string') {
171
+ try {
172
+ obj.submission = JSON.parse(obj.submission);
173
+ }
174
+ catch { }
175
+ }
176
+ if (typeof obj.info === 'string') {
177
+ try {
178
+ obj.info = JSON.parse(obj.info);
179
+ }
180
+ catch { }
181
+ }
182
+ return obj;
183
+ }
184
+ return input;
185
+ }, z.discriminatedUnion("operation_type", [
186
+ z.object({
187
+ operation_type: z.literal("service"),
188
+ data: CallService_DataSchema,
189
+ env: CallEnvSchema.optional(),
190
+ submission: SubmissionCallSchema.optional(),
191
+ }).describe("πŸͺ Service Object: Create and manage product/service listings with transparent promises, bind workflow templates to order processing, set pricing, issue discount coupons to customers, and establish quality standards, etc.."),
192
+ z.object({
193
+ operation_type: z.literal("machine"),
194
+ data: CallMachine_DataSchema,
195
+ env: CallEnvSchema.optional(),
196
+ submission: SubmissionCallSchema.optional(),
197
+ }).describe("βš™οΈ Machine Object: Design and deploy automated workflow templates (Machines) that define how services are delivered, etc.."),
198
+ z.object({
199
+ operation_type: z.literal("progress"),
200
+ data: CallProgress_DataSchema,
201
+ env: CallEnvSchema.optional(),
202
+ submission: SubmissionCallSchema.optional(),
203
+ }).describe("πŸ“Š Progress Object: Track and manage active workflows in real-time."),
204
+ z.object({
205
+ operation_type: z.literal("repository"),
206
+ data: CallRepository_DataSchema,
207
+ env: CallEnvSchema.optional(),
208
+ submission: SubmissionCallSchema.optional(),
209
+ }).describe("πŸ“¦ Repository Object: Read/write database with consensus field + address as key, strongly-typed data as value."),
210
+ z.object({
211
+ operation_type: z.literal("arbitration"),
212
+ data: CallArbitration_DataSchema,
213
+ env: CallEnvSchema.optional(),
214
+ submission: SubmissionCallSchema.optional(),
215
+ }).describe("βš–οΈ Arbitration Object: Access a transparent on-chain arbitration system for resolving order conflicts."),
216
+ z.object({
217
+ operation_type: z.literal("contact"),
218
+ data: CallContact_DataSchema,
219
+ env: CallEnvSchema.optional(),
220
+ submission: SubmissionCallSchema.optional(),
221
+ }).describe("πŸ’¬ Contact Object: Manage on-chain instant messaging contact profiles."),
222
+ z.object({
223
+ operation_type: z.literal("treasury"),
224
+ data: CallTreasury_DataSchema,
225
+ env: CallEnvSchema.optional(),
226
+ submission: SubmissionCallSchema.optional(),
227
+ }).describe("πŸ’° Treasury Object: Create and manage treasury for team funds with deposit/withdrawal rules, etc.."),
228
+ z.object({
229
+ operation_type: z.literal("reward"),
230
+ data: CallReward_DataSchema,
231
+ env: CallEnvSchema.optional(),
232
+ submission: SubmissionCallSchema.optional(),
233
+ }).describe("🎁 Reward Object: Create reward pools and set claim conditions by Guard verification."),
234
+ z.object({
235
+ operation_type: z.literal("allocation"),
236
+ data: CallAllocation_DataSchema,
237
+ env: CallEnvSchema.optional(),
238
+ submission: SubmissionCallSchema.optional(),
239
+ }).describe("πŸ“€ Allocation Object: Create distribution plans to auto-distribute funds to multiple recipients."),
240
+ z.object({
241
+ operation_type: z.literal("permission"),
242
+ data: CallPermission_DataSchema,
243
+ env: CallEnvSchema.optional(),
244
+ }).describe("πŸ” Permission Object: Define who can perform which operations on WoWok objects. Important Note: If needed, you should first query 'guard instructions' through the 'wowok_buildin_info' tool."),
245
+ z.object({
246
+ operation_type: z.literal("guard"),
247
+ data: CallGuard_DataSchema,
248
+ env: CallEnvSchema.optional(),
249
+ }).describe("πŸ›‘οΈ Guard Object: Create immutable programmable validation rules that return boolean results. Set 'namedNew' to name the new Guard. Use root.type='node' for direct node tree or root.type='file' to load from file. Use 'wowok_buildin_info' tool with query='guard instructions' for all available operations. NOTE for EntityLinker/EntityRegistrar queries: Add system addresses to the Guard table - ENTITY_LINKER_ADDRESS (0xaaa) for EntityLinker, ENTITY_REGISTRAR_ADDRESS (0xaab) for EntityRegistrar."),
250
+ z.object({
251
+ operation_type: z.literal("personal"),
252
+ data: CallPersonal_DataSchema,
253
+ env: CallEnvSchema.optional(),
254
+ }).describe("πŸ†” Public Identity Profile: Establish and manage your on-chain public identity. ⚠️ CRITICAL: Everything here is PERMANENTLY PUBLIC on the blockchain!"),
255
+ z.object({
256
+ operation_type: z.literal("payment"),
257
+ data: CallPayment_DataSchema,
258
+ env: CallEnvSchema.optional(),
259
+ }).describe("πŸ’° Payment Object: Send instant, irreversible coin transfers to any wallet address."),
260
+ z.object({
261
+ operation_type: z.literal("demand"),
262
+ data: CallDemand_DataSchema,
263
+ env: CallEnvSchema.optional(),
264
+ submission: SubmissionCallSchema.optional(),
265
+ }).describe("🎯 Demand Object: Post service requests with reward pools on-chain."),
266
+ z.object({
267
+ operation_type: z.literal("order"),
268
+ data: CallOrder_DataSchema,
269
+ env: CallEnvSchema.optional(),
270
+ submission: SubmissionCallSchema.optional(),
271
+ }).describe("πŸ“¦ Order Object: Manage the order lifecycle, Including operating order arbitration (Arb Object associated with the order), advancing progress (Progress Object associated with the order), extracting order refunds/payments, setting agents, etc."),
272
+ z.object({
273
+ operation_type: z.literal("gen_passport"),
274
+ guard: z.union([z.string(), z.array(z.string())]).describe("Guard object ID(s) to verify and generate passport from. Can be a single guard (string) or multiple guards (array of strings). Supports guard names or addresses."),
275
+ info: SubmissionCallSchema.optional().describe("Optional submission data. If not provided, will attempt to get existing submissions from the guard."),
276
+ env: CallEnvSchema.optional(),
277
+ }).describe("πŸ›‚ Generate Verified Passport Object: Create immutable verified credentials after Guard validation passes. Supports verifying multiple guards at once."),
278
+ ]));
279
+ const WipOperationsSchema = z.preprocess((input) => {
280
+ if (typeof input === 'object' && input !== null) {
281
+ const obj = { ...input };
282
+ if (typeof obj.description === 'string' && !obj.type) {
283
+ try {
284
+ const parsed = JSON.parse(obj.description);
285
+ if (parsed && typeof parsed === 'object' && parsed.type) {
286
+ return parsed;
287
+ }
288
+ }
289
+ catch { }
290
+ }
291
+ if (typeof obj.options === 'string') {
292
+ try {
293
+ obj.options = JSON.parse(obj.options);
294
+ }
295
+ catch { }
296
+ }
297
+ return obj;
298
+ }
299
+ return input;
300
+ }, z.discriminatedUnion("type", [
301
+ z.object({
302
+ type: z.literal("generate"),
303
+ options: WipGenerationOptionsSchema.describe("WIP generation options"),
304
+ outputPath: z.string().describe("Output file path (.wip file). If file exists, it will be overwritten"),
305
+ }).describe("Generate WIP file from markdown text and optional images"),
306
+ z.object({
307
+ type: z.literal("verify"),
308
+ wipFilePath: z.string().describe("WIP file path to verify. Supports: 1) Local file path (e.g., '/path/to/file.wip', 'C:\\Users\\name\\doc.wip'), 2) Network URL (e.g., 'https://example.com/doc.wip', 'http://site.com/file.wip'), 3) Data URL (e.g., 'data:application/json;base64,eyJ3aXAiOi...')"),
309
+ hash_equal: z.string().optional().describe("Optional expected hash value. If provided, the function will first verify if the file's hash matches this value. If not matched, returns hash mismatch error."),
310
+ requireSignature: z.boolean().optional().describe("Optional flag to require digital signature. If true, verification will fail if WIP file has no signature"),
311
+ }).describe("Verify WIP file integrity and signatures"),
312
+ z.object({
313
+ type: z.literal("sign"),
314
+ wipFilePath: z.string().describe("WIP file path to sign. Supports: 1) Local file path (e.g., '/path/to/file.wip'), 2) Network URL (e.g., 'https://example.com/doc.wip'). The file will be loaded, validated, and signed"),
315
+ account: z.string().optional().describe("Signing account (account name or address). If not specified, uses default account"),
316
+ outputPath: z.string().optional().describe("Output file path. If not specified, adds 'signed_' prefix to original file name (e.g., 'doc.wip' becomes 'signed_doc.wip')"),
317
+ }).describe("Sign WIP file with account"),
318
+ z.object({
319
+ type: z.literal("wip2html"),
320
+ wipPath: z.string().describe("WIP file path or directory path. Supports: 1) Single WIP file (e.g., '/path/to/file.wip'), 2) Directory containing .wip files (e.g., '/path/to/wips/'), 3) Network URL (e.g., 'https://example.com/doc.wip'). When directory is provided, all .wip files in the directory will be converted to HTML"),
321
+ options: WipToHtmlOptionsSchema.optional().describe("Conversion options"),
322
+ }).describe("Convert WIP file to HTML format"),
323
+ ]));
324
+ const OnchainTableDataSchema = z.preprocess((input) => {
325
+ if (typeof input === 'object' && input !== null && !Array.isArray(input)) {
326
+ const obj = { ...input };
327
+ if (typeof obj.description === 'string' && !obj.query_type) {
328
+ try {
329
+ const parsed = JSON.parse(obj.description);
330
+ if (parsed && typeof parsed === 'object' && parsed.query_type) {
331
+ return parsed;
332
+ }
333
+ }
334
+ catch { }
335
+ }
336
+ if (obj.cursor === '')
337
+ obj.cursor = null;
338
+ if (obj.limit === '')
339
+ obj.limit = null;
340
+ return obj;
341
+ }
342
+ return input;
343
+ }, z.union([
344
+ z.discriminatedUnion("query_type", [
345
+ z.object({
346
+ query_type: z.literal("onchain_table"),
347
+ parent: NameOrAddressSchema.describe("Parent object ID whose dynamic fields table to query"),
348
+ cursor: z.union([z.string(), z.null()]).optional().describe("Pagination cursor from previous page's nextCursor"),
349
+ limit: z.union([z.number(), z.null()]).optional().describe("Max items per page"),
350
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
351
+ network: EntrypointSchema.optional(),
352
+ }).describe("Paginated query of an on-chain object's dynamic fields table β€” returns items with keys, types, and object IDs. Use to explore all entries (e.g., all orders in a Service, all records in a Repository). Returns: TableAnswer | undefined (items[], nextCursor, hasNextPage)"),
353
+ z.object({
354
+ query_type: z.literal("onchain_table_item_repository_data"),
355
+ parent: NameOrAddressSchema.describe("Parent Repository object ID"),
356
+ name: z.string().describe("Name/key of the record to retrieve from the repository"),
357
+ entity: z.union([AccountOrMark_AddressSchema, z.number()]).describe("Entity ID or address that owns/identifies the record"),
358
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
359
+ network: EntrypointSchema.optional(),
360
+ }).describe("Query a specific record from a Repository's on-chain key-value database by name and entity. Use to read stored data records. Returns: TableItem_RepositoryData | undefined"),
361
+ z.object({
362
+ query_type: z.literal("onchain_table_item_permission_perm"),
363
+ parent: NameOrAddressSchema.describe("Parent Permission object ID"),
364
+ address: z.union([AccountOrMark_AddressSchema, z.string()]).describe("User address or Guard ID whose permissions to check"),
365
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
366
+ network: EntrypointSchema.optional(),
367
+ }).describe("Query a permission entry from a Permission object's perm table β€” checks what operations a user/guard is allowed to perform. Use to verify access rights. Returns: TableItem_PermissionPerm | undefined"),
368
+ z.object({
369
+ query_type: z.literal("onchain_table_item_entity_registrar"),
370
+ address: z.union([AccountOrMark_AddressSchema, z.string()]).describe("User address to look up in the global EntityRegistrar"),
371
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
372
+ network: EntrypointSchema.optional(),
373
+ }).describe("Query an entity's registration record from the global EntityRegistrar β€” verifies if an address is registered on the blockchain. Use to check registration status and details. Returns: TableItem_EntityRegistrar | undefined"),
374
+ z.object({
375
+ query_type: z.literal("onchain_table_item_entity_linker"),
376
+ address: z.union([AccountOrMark_AddressSchema, z.string()]).describe("Entity address whose community votes/endorsements to query"),
377
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
378
+ network: EntrypointSchema.optional(),
379
+ }).describe("Query community votes/endorsements for an entity from the global EntityLinker β€” shows how others have voted on this entity. Use to check reputation and community trust. Returns: TableItem_EntityLinker | undefined"),
380
+ z.object({
381
+ query_type: z.literal("onchain_table_item_reward_record"),
382
+ parent: NameOrAddressSchema.describe("Parent Reward object ID"),
383
+ address: AccountOrMark_AddressSchema.describe("User address that claimed the reward"),
384
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
385
+ network: EntrypointSchema.optional(),
386
+ }).describe("Query a reward claim record from a Reward object's table β€” checks if a user has claimed a specific incentive. Use to verify reward distribution status. Returns: TableItem_RewardRecord | undefined"),
387
+ ]),
388
+ z.discriminatedUnion("query_type", [
389
+ z.object({
390
+ query_type: z.literal("onchain_table_item_demand_presenter"),
391
+ parent: NameOrAddressSchema.describe("Parent Demand object ID"),
392
+ address: AccountOrMark_AddressSchema.describe("Presenter address that submitted the demand"),
393
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
394
+ network: EntrypointSchema.optional(),
395
+ }).describe("Query a demand submission from a Demand object's table β€” Demands are service requests submitted by users. Use to check a specific demand's details. Returns: TableItem_DemandPresenter | undefined"),
396
+ z.object({
397
+ query_type: z.literal("onchain_table_item_treasury_history"),
398
+ parent: NameOrAddressSchema.describe("Parent Treasury object ID"),
399
+ address: AccountOrMark_AddressSchema.describe("Payment ID whose treasury record to look up"),
400
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
401
+ network: EntrypointSchema.optional(),
402
+ }).describe("Query a payment record from a Treasury's history table by payment ID β€” Treasury manages funds and payment tracking. Use to look up payment details and status. Returns: TableItem_TreasuryHistory | undefined"),
403
+ z.object({
404
+ query_type: z.literal("onchain_table_item_machine_node"),
405
+ parent: NameOrAddressSchema.describe("Parent Machine object ID"),
406
+ key: z.string().describe("Node name (string key) to query in the Machine's workflow definition"),
407
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
408
+ network: EntrypointSchema.optional(),
409
+ }).describe("Query a workflow node definition from a Machine object's table by node name β€” Machines define workflow templates. Use to inspect a specific node's configuration and logic. Returns: TableItem_MachineNode | undefined"),
410
+ z.object({
411
+ query_type: z.literal("onchain_table_item_progress_history"),
412
+ parent: NameOrAddressSchema.describe("Parent Progress object ID"),
413
+ u64: z.union([z.number(), z.string()]).describe("Sequence number (u64) of the progress step to query"),
414
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
415
+ network: EntrypointSchema.optional(),
416
+ }).describe("Query a progress step record from a Progress object's table by sequence number β€” Progress tracks order/workflow execution. Use to check the status of a specific execution step. Returns: TableItem_ProgressHistory | undefined"),
417
+ z.object({
418
+ query_type: z.literal("onchain_table_item_address_mark"),
419
+ parent: NameOrAddressSchema.describe("Parent AddressMark object ID"),
420
+ address: AccountOrMark_AddressSchema.describe("Address whose PUBLIC on-chain name/tags to look up"),
421
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
422
+ network: EntrypointSchema.optional(),
423
+ }).describe("Query a PUBLIC on-chain name/tag mark for an address β€” unlike local marks, these are published on-chain. Use to look up public labels attached to any address. Returns: TableItem_AddressMark | undefined"),
424
+ z.object({
425
+ query_type: z.literal("onchain_table_item_generic"),
426
+ parent: NameOrAddressSchema.describe("Parent object ID whose dynamic field to query"),
427
+ key_type: z.string().describe("Type of the key (e.g., 'address', 'u64', 'string', '0x2::object::ID')"),
428
+ key_value: z.any().describe("Value of the key. Must match the key_type format"),
429
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
430
+ network: EntrypointSchema.optional(),
431
+ }).describe("Query a generic table item from ANY object's dynamic fields β€” supports arbitrary key types and values for non-WoWok objects. Use for custom objects and general-purpose table lookups. Returns: ObjectBase | undefined"),
432
+ ]),
433
+ ]));
434
+ const OnchainTableDataResultSchema = z.object({
435
+ result: z.union([
436
+ z.object({ query_type: z.literal("onchain_table"), result: z.union([TableAnswerSchema, z.undefined()]) }),
437
+ z.object({ query_type: z.literal("onchain_table_item_repository_data"), result: z.union([TableItem_RepositoryDataSchema, z.undefined()]) }),
438
+ z.object({ query_type: z.literal("onchain_table_item_permission_perm"), result: z.union([TableItem_PermissionPermSchema, z.undefined()]) }),
439
+ z.object({ query_type: z.literal("onchain_table_item_entity_registrar"), result: z.union([TableItem_EntityRegistrarSchema, z.undefined()]) }),
440
+ z.object({ query_type: z.literal("onchain_table_item_entity_linker"), result: z.union([TableItem_EntityLinkerSchema, z.undefined()]) }),
441
+ z.object({ query_type: z.literal("onchain_table_item_reward_record"), result: z.union([TableItem_RewardRecordSchema, z.undefined()]) }),
442
+ z.object({ query_type: z.literal("onchain_table_item_demand_presenter"), result: z.union([TableItem_DemandPresenterSchema, z.undefined()]) }),
443
+ z.object({ query_type: z.literal("onchain_table_item_treasury_history"), result: z.union([TableItem_TreasuryHistorySchema, z.undefined()]) }),
444
+ z.object({ query_type: z.literal("onchain_table_item_machine_node"), result: z.union([TableItem_MachineNodeSchema, z.undefined()]) }),
445
+ z.object({ query_type: z.literal("onchain_table_item_progress_history"), result: z.union([TableItem_ProgressHistorySchema, z.undefined()]) }),
446
+ z.object({ query_type: z.literal("onchain_table_item_address_mark"), result: z.union([TableItem_AddressMarkSchema, z.undefined()]) }),
447
+ z.object({ query_type: z.literal("onchain_table_item_generic"), result: z.union([ObjectBaseSchema, z.undefined()]) }),
448
+ ])
449
+ });
450
+ async function handleOnchainTableData(args) {
451
+ const validated = strictParse(OnchainTableDataSchema, args, "onchain_table_data input");
452
+ let result;
453
+ switch (validated.query_type) {
454
+ case "onchain_table": {
455
+ const queryResult = await query_table({ parent: validated.parent, cursor: validated.cursor, limit: validated.limit, no_cache: validated.no_cache, network: validated.network });
456
+ result = { query_type: "onchain_table", result: queryResult };
457
+ break;
458
+ }
459
+ case "onchain_table_item_repository_data": {
460
+ const queryResult = await queryTableItem_RepositoryData({ parent: validated.parent, name: validated.name, entity: validated.entity, no_cache: validated.no_cache, network: validated.network });
461
+ result = { query_type: "onchain_table_item_repository_data", result: queryResult };
462
+ break;
463
+ }
464
+ case "onchain_table_item_permission_perm": {
465
+ const queryResult = await queryTableItem_PermissionPerm({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
466
+ result = { query_type: "onchain_table_item_permission_perm", result: queryResult };
467
+ break;
468
+ }
469
+ case "onchain_table_item_reward_record": {
470
+ const queryResult = await queryTableItem_RewardRecord({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
471
+ result = { query_type: "onchain_table_item_reward_record", result: queryResult };
472
+ break;
473
+ }
474
+ case "onchain_table_item_demand_presenter": {
475
+ const queryResult = await queryTableItem_DemandPresenter({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
476
+ result = { query_type: "onchain_table_item_demand_presenter", result: queryResult };
477
+ break;
478
+ }
479
+ case "onchain_table_item_treasury_history": {
480
+ const queryResult = await queryTableItem_TreasuryHistory({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
481
+ result = { query_type: "onchain_table_item_treasury_history", result: queryResult };
482
+ break;
483
+ }
484
+ case "onchain_table_item_machine_node": {
485
+ const queryResult = await queryTableItem_MachineNode({ parent: validated.parent, key: validated.key, no_cache: validated.no_cache, network: validated.network });
486
+ result = { query_type: "onchain_table_item_machine_node", result: queryResult };
487
+ break;
488
+ }
489
+ case "onchain_table_item_progress_history": {
490
+ const queryResult = await queryTableItem_ProgressHistory({ parent: validated.parent, u64: validated.u64, no_cache: validated.no_cache, network: validated.network });
491
+ result = { query_type: "onchain_table_item_progress_history", result: queryResult };
492
+ break;
493
+ }
494
+ case "onchain_table_item_address_mark": {
495
+ const queryResult = await queryTableItem_AddressMark({ parent: validated.parent, address: validated.address, no_cache: validated.no_cache, network: validated.network });
496
+ result = { query_type: "onchain_table_item_address_mark", result: queryResult };
497
+ break;
498
+ }
499
+ case "onchain_table_item_entity_registrar": {
500
+ const queryResult = await queryTableItem_EntityRegistrar({ address: validated.address, no_cache: validated.no_cache, network: validated.network });
501
+ result = { query_type: "onchain_table_item_entity_registrar", result: queryResult };
502
+ break;
503
+ }
504
+ case "onchain_table_item_entity_linker": {
505
+ const queryResult = await queryTableItem_EntityLinker({ address: validated.address, no_cache: validated.no_cache, network: validated.network });
506
+ result = { query_type: "onchain_table_item_entity_linker", result: queryResult };
507
+ break;
508
+ }
509
+ case "onchain_table_item_generic": {
510
+ const queryResult = await query_tableItem({
511
+ parent: validated.parent,
512
+ key: { type: validated.key_type, value: validated.key_value },
513
+ no_cache: validated.no_cache,
514
+ network: validated.network
515
+ });
516
+ result = { query_type: "onchain_table_item_generic", result: queryResult };
517
+ break;
518
+ }
519
+ default:
520
+ throw new Error(`Unknown table query type. Valid query_types are: "onchain_table", "onchain_table_item_repository_data", "onchain_table_item_permission_perm", "onchain_table_item_reward_record", "onchain_table_item_demand_presenter", "onchain_table_item_treasury_history", "onchain_table_item_machine_node", "onchain_table_item_progress_history", "onchain_table_item_address_mark", "onchain_table_item_entity_registrar", "onchain_table_item_entity_linker", "onchain_table_item_generic"`);
521
+ }
522
+ return {
523
+ content: [{ type: "text", text: JSON.stringify({ result }) }],
524
+ structuredContent: { result },
525
+ };
526
+ }
527
+ const WatchQueryOperationsSchema = z.preprocess((input) => {
528
+ if (typeof input === 'object' && input !== null) {
529
+ const obj = { ...input };
530
+ if (typeof obj.description === 'string' && !obj.query_type) {
531
+ try {
532
+ const parsed = JSON.parse(obj.description);
533
+ if (parsed && typeof parsed === 'object' && parsed.query_type) {
534
+ return parsed;
535
+ }
536
+ }
537
+ catch { }
538
+ }
539
+ for (const key of ['filter', 'objects', 'env', 'token_type']) {
540
+ if (typeof obj[key] === 'string') {
541
+ try {
542
+ obj[key] = JSON.parse(obj[key]);
543
+ }
544
+ catch { }
545
+ }
546
+ }
547
+ return obj;
548
+ }
549
+ return input;
550
+ }, z.union([
551
+ z.discriminatedUnion("query_type", [
552
+ z.object({
553
+ query_type: z.literal("local_mark_list"),
554
+ filter: LocalMarkFilterSchema.optional().describe("Local mark filter"),
555
+ }).describe("Query your LOCAL address book — maps human-readable names to blockchain addresses with optional tags. Use to resolve names→addresses or find addresses by tag. Returns: MarkData[] (name, address, tags, timestamps)"),
556
+ z.object({
557
+ query_type: z.literal("account_list"),
558
+ filter: AccountFilterSchema.optional().describe("Account filter"),
559
+ }).describe("Query your LOCAL accounts β€” view all accounts stored on this device (addresses, public keys, messenger status, suspension state). Use to discover available accounts before operations. Returns: AccountData[] (name, address, pubkey, suspended, messenger, timestamps)"),
560
+ z.object({
561
+ query_type: z.literal("local_info_list"),
562
+ filter: LocalInfoFilterSchema.optional().describe("Local info filter"),
563
+ }).describe("Query your LOCAL private info β€” sensitive data like delivery addresses, phone numbers, contacts stored ONLY on this device. Use to retrieve saved contact/delivery details. Returns: InfoData[] (name, default value, contents, timestamps)"),
564
+ z.object({
565
+ query_type: z.literal("token_list"),
566
+ filter: TokenDataFilterSchema.optional(),
567
+ }).describe("Query cached token metadata β€” symbol, decimals, icon URL, description for tokens previously fetched from chain. Use to look up token info without an on-chain query. Returns: TokenTypeInfo[] (type, alias, name, symbol, decimals, iconUrl)"),
568
+ z.object({
569
+ query_type: z.literal("account_balance"),
570
+ name_or_address: NameOrAddressSchema.optional().describe("Account name or address. Use empty string '' for the default account. Defaults to '' if omitted."),
571
+ balance: z.boolean().optional().describe("Set to true to query total balance amount for the token type"),
572
+ coin: z.object({
573
+ cursor: z.union([z.string(), z.null()]).optional().describe("Pagination cursor for listing coin objects"),
574
+ limit: z.union([z.number(), z.null()]).optional().describe("Max coin objects per page"),
575
+ }).optional().describe("Set to query paginated coin objects instead of balance. Use cursor/limit for pagination."),
576
+ token_type: TokenTypeSchema.optional().describe("Token type to query; defaults to 0x2::wow::WOW (platform token)"),
577
+ network: EntrypointSchema.optional(),
578
+ }).describe("Query an account's coin balance OR paginated coin objects. Use balance=true for total amount, or coin={cursor,limit} to list individual coin objects. Returns: { address, balance? | coin? }"),
579
+ ]),
580
+ z.discriminatedUnion("query_type", [
581
+ z.object({
582
+ query_type: z.literal("onchain_personal_profile"),
583
+ account: NameOrAddressSchema.optional().describe("Account name or ID to query. Use empty string '' for the default account."),
584
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
585
+ network: EntrypointSchema.optional(),
586
+ }).describe("Query any user's PUBLIC on-chain profile β€” social links, reputation (likes/dislikes), personal info records, voting history, referrer. Use to look up a user's public identity and reputation. Returns: ObjectPersonal | undefined"),
587
+ z.object({
588
+ query_type: z.literal("onchain_objects"),
589
+ objects: z.array(NameOrAddressSchema).describe("List of object IDs (names or addresses) to query in batch"),
590
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
591
+ network: EntrypointSchema.optional(),
592
+ }).describe("Batch query on-chain WOWOK objects by ID or name β€” supports Service, Machine, Order, Treasury, Reward, Arb, Personal, Contact, and more. Use to inspect one or more objects in a single call. Returns: { objects: ObjectBase[] }"),
593
+ z.object({
594
+ query_type: z.literal("onchain_received"),
595
+ name_or_address: AccountOrMark_AddressAISchema.describe("Name or address of the object that received payments/items - can be a string (name/address) or full object"),
596
+ all_type: z.boolean().optional().describe("Set to true to query all token types received; defaults to the object's Token type '0x2::payment::CoinWrapper<TOKEN>' (Coins wrapper sent via Payment object). If the object has no Token type, the call will fail."),
597
+ cursor: z.union([z.string(), z.null()]).optional().describe("Pagination cursor from previous page"),
598
+ limit: z.union([z.number(), z.null()]).optional().describe("Max records per page"),
599
+ no_cache: z.boolean().optional().describe("Set to true to bypass cache and fetch fresh on-chain data"),
600
+ network: EntrypointSchema.optional(),
601
+ }).describe("Query objects (Payments, Tokens, NFTs) received by a specific object. Use to track incoming payments or items sent to an on-chain object. Supports pagination and all_type filter. Returns: ReceivedBalance | ReceivedNormal[]"),
602
+ ]),
603
+ ]));
604
+ async function handleOnchainOperations(args) {
605
+ try {
606
+ if (typeof args === 'object' && args !== null && args.description && !args.operation_type) {
607
+ const hasWrappedParams = typeof args.description === 'string' &&
608
+ (args.description.includes('operation_type') || args.description.includes('data'));
609
+ if (hasWrappedParams) {
610
+ throw new Error("Invalid parameter structure. Parameters should NOT be wrapped in 'description' field.\n" +
611
+ "Correct format: { operation_type: '...', data: {...} }\n" +
612
+ "Incorrect format: { description: '{ operation_type: ... }' }");
613
+ }
614
+ }
615
+ const validated = strictParse(OnchainOperationsSchema, args, "onchain_operations input");
616
+ const env = getEnvConfig(validated.env);
617
+ switch (validated.operation_type) {
618
+ case "service": {
619
+ const callService = new CallService(validated.data);
620
+ const result = validated.submission
621
+ ? await callService.call_with_submission(env, await transformSubmission(validated.submission))
622
+ : await callService.call(env);
623
+ return handleCallResult(result);
624
+ }
625
+ case "machine": {
626
+ if (validated.data.node && typeof validated.data.node === 'object' && 'json_or_markdown_file' in validated.data.node) {
627
+ const filePathStr = validated.data.node.json_or_markdown_file;
628
+ let fileContent;
629
+ try {
630
+ const filePath = resolve(filePathStr);
631
+ fileContent = readFileSync(filePath, 'utf-8');
632
+ }
633
+ catch (e) {
634
+ throw new Error(`Failed to read file '${filePathStr}': ${e.message}`);
635
+ }
636
+ const parseResult = parseMachineNodesFromText(fileContent);
637
+ if (!parseResult.success) {
638
+ const errorMessages = formatMachineNodeErrors(parseResult.errors);
639
+ throw new Error(`Machine node validation failed for file '${filePathStr}':\n\n${errorMessages}`);
640
+ }
641
+ if (!parseResult.data) {
642
+ throw new Error(`No nodes found in file '${filePathStr}'`);
643
+ }
644
+ validated.data.node = {
645
+ op: "set",
646
+ nodes: parseResult.data,
647
+ bReplace: true
648
+ };
649
+ }
650
+ const callMachine = new CallMachine(validated.data);
651
+ const result = validated.submission
652
+ ? await callMachine.call_with_submission(env, await transformSubmission(validated.submission))
653
+ : await callMachine.call(env);
654
+ return handleCallResult(result);
655
+ }
656
+ case "progress": {
657
+ const callProgress = new CallProgress(validated.data);
658
+ const result = validated.submission
659
+ ? await callProgress.call_with_submission(env, await transformSubmission(validated.submission))
660
+ : await callProgress.call(env);
661
+ return handleCallResult(result);
662
+ }
663
+ case "repository": {
664
+ const callRepository = new CallRepository(validated.data);
665
+ const result = validated.submission
666
+ ? await callRepository.call_with_submission(env, await transformSubmission(validated.submission))
667
+ : await callRepository.call(env);
668
+ return handleCallResult(result);
669
+ }
670
+ case "arbitration": {
671
+ const callArbitration = new CallArbitration(validated.data);
672
+ const result = validated.submission
673
+ ? await callArbitration.call_with_submission(env, await transformSubmission(validated.submission))
674
+ : await callArbitration.call(env);
675
+ return handleCallResult(result);
676
+ }
677
+ case "contact": {
678
+ const callContact = new CallContact(validated.data);
679
+ const result = validated.submission
680
+ ? await callContact.call_with_submission(env, await transformSubmission(validated.submission))
681
+ : await callContact.call(env);
682
+ return handleCallResult(result);
683
+ }
684
+ case "treasury": {
685
+ const callTreasury = new CallTreasury(validated.data);
686
+ const result = validated.submission
687
+ ? await callTreasury.call_with_submission(env, await transformSubmission(validated.submission))
688
+ : await callTreasury.call(env);
689
+ return handleCallResult(result);
690
+ }
691
+ case "reward": {
692
+ const transformedData = transformRewardData(validated.data);
693
+ const callReward = new CallReward(transformedData);
694
+ const result = validated.submission
695
+ ? await callReward.call_with_submission(env, await transformSubmission(validated.submission))
696
+ : await callReward.call(env);
697
+ return handleCallResult(result);
698
+ }
699
+ case "allocation": {
700
+ const callAllocation = new CallAllocation(validated.data);
701
+ const result = validated.submission
702
+ ? await callAllocation.call_with_submission(env, await transformSubmission(validated.submission))
703
+ : await callAllocation.call(env);
704
+ return handleCallResult(result);
705
+ }
706
+ case "permission": {
707
+ const callPermission = new CallPermission(validated.data);
708
+ const result = await callPermission.call(env);
709
+ return handleCallResult(result);
710
+ }
711
+ case "guard": {
712
+ const validatedData = validated.data;
713
+ if (validatedData.root?.type === "file") {
714
+ const filePath = resolve(validatedData.root.file_path);
715
+ let fileContent;
716
+ try {
717
+ fileContent = readFileSync(filePath, 'utf-8');
718
+ }
719
+ catch (e) {
720
+ throw new Error(`Failed to read Guard definition file '${validatedData.root.file_path}': ${e.message}`);
721
+ }
722
+ const parseResult = parseGuardFile(fileContent, validatedData.root.format);
723
+ if (!parseResult.success) {
724
+ const errorMessages = formatGuardParseErrors(parseResult.errors);
725
+ throw new Error(`Guard validation failed for file '${validatedData.root.file_path}':\n\n${errorMessages}`);
726
+ }
727
+ const fileData = parseResult.data;
728
+ validatedData.root = { type: "node", node: fileData.root };
729
+ if (fileData.table !== undefined && validatedData.table === undefined) {
730
+ validatedData.table = fileData.table;
731
+ }
732
+ if (fileData.description !== undefined && validatedData.description === undefined) {
733
+ validatedData.description = fileData.description;
734
+ }
735
+ if (fileData.rely !== undefined && validatedData.rely === undefined) {
736
+ validatedData.rely = fileData.rely;
737
+ }
738
+ if (fileData.namedNew !== undefined && validatedData.namedNew === undefined) {
739
+ validatedData.namedNew = fileData.namedNew;
740
+ }
741
+ }
742
+ if (validatedData.root && typeof validatedData.root === 'object') {
743
+ const rootObj = validatedData.root;
744
+ if (rootObj.type === 'node' && rootObj.node) {
745
+ validatedData.root = rootObj.node;
746
+ }
747
+ }
748
+ if (!validatedData.table || validatedData.table.length === 0) {
749
+ throw new Error("Guard 'table' field is required and cannot be empty");
750
+ }
751
+ if (!validatedData.root) {
752
+ throw new Error("Guard 'root' field is required");
753
+ }
754
+ const callGuard = new CallGuard(validatedData);
755
+ const result = await callGuard.call(env);
756
+ return handleCallResult(result);
757
+ }
758
+ case "personal": {
759
+ const transformPersonalData = (data) => {
760
+ const result = { ...data };
761
+ if (data.mark) {
762
+ const transformAddress = (addr) => {
763
+ if (typeof addr === 'string') {
764
+ return { name_or_address: addr, local_mark_first: true };
765
+ }
766
+ return addr;
767
+ };
768
+ if (data.mark.op === 'add' && data.mark.data) {
769
+ result.mark = {
770
+ ...data.mark,
771
+ data: data.mark.data.map((item) => ({
772
+ ...item,
773
+ address: transformAddress(item.address)
774
+ }))
775
+ };
776
+ }
777
+ else if (data.mark.op === 'remove' && data.mark.data) {
778
+ result.mark = {
779
+ ...data.mark,
780
+ data: data.mark.data.map((item) => ({
781
+ ...item,
782
+ address: transformAddress(item.address)
783
+ }))
784
+ };
785
+ }
786
+ else if (data.mark.op === 'clear' && data.mark.address) {
787
+ const addr = data.mark.address;
788
+ if (Array.isArray(addr) && addr.every((a) => typeof a === 'string')) {
789
+ result.mark = {
790
+ ...data.mark,
791
+ address: {
792
+ entities: addr.map((a) => ({ name_or_address: a, local_mark_first: true }))
793
+ }
794
+ };
795
+ }
796
+ }
797
+ else if (data.mark.op === 'transfer' && data.mark.to) {
798
+ result.mark = {
799
+ ...data.mark,
800
+ to: transformAddress(data.mark.to)
801
+ };
802
+ }
803
+ }
804
+ return result;
805
+ };
806
+ const transformedData = transformPersonalData(validated.data);
807
+ const callPersonal = new CallPersonal(transformedData);
808
+ const result = await callPersonal.call(env);
809
+ return handleCallResult(result);
810
+ }
811
+ case "payment": {
812
+ const callPayment = new CallPayment(validated.data);
813
+ const result = await callPayment.call(env);
814
+ return handleCallResult(result);
815
+ }
816
+ case "demand": {
817
+ const callDemand = new CallDemand(validated.data);
818
+ const result = validated.submission
819
+ ? await callDemand.call_with_submission(env, await transformSubmission(validated.submission))
820
+ : await callDemand.call(env);
821
+ return handleCallResult(result);
822
+ }
823
+ case "order": {
824
+ const callOrder = new CallOrder(validated.data);
825
+ const result = validated.submission
826
+ ? await callOrder.call_with_submission(env, await transformSubmission(validated.submission))
827
+ : await callOrder.call(env);
828
+ return handleCallResult(result);
829
+ }
830
+ case "gen_passport": {
831
+ const result = await gen_passport(env, validated.guard, validated.info);
832
+ return handleCallResult(result);
833
+ }
834
+ }
835
+ throw new Error(`Unknown on-chain operation type: ${validated.operation_type}`);
836
+ }
837
+ catch (error) {
838
+ const errorMessage = error instanceof Error ? error.message : String(error);
839
+ return {
840
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
841
+ structuredContent: {
842
+ message: `Error: ${errorMessage}`,
843
+ result: {
844
+ type: "error",
845
+ error: errorMessage,
846
+ },
847
+ },
848
+ };
849
+ }
850
+ }
851
+ async function handleAccountOperation(args) {
852
+ try {
853
+ const validated = strictParse(AccountOperationSchema, args, "account_operation input");
854
+ const result = await account_operation(validated);
855
+ return {
856
+ content: [{ type: "text", text: JSON.stringify(result) }],
857
+ structuredContent: {
858
+ result: {
859
+ status: "success",
860
+ data: result,
861
+ },
862
+ },
863
+ };
864
+ }
865
+ catch (error) {
866
+ const errorMessage = error instanceof Error ? error.message : String(error);
867
+ return {
868
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
869
+ structuredContent: {
870
+ result: {
871
+ status: "error",
872
+ error: errorMessage,
873
+ },
874
+ },
875
+ };
876
+ }
877
+ }
878
+ async function handleMarkOperation(args) {
879
+ try {
880
+ const validated = strictParse(LocalMarkOperationSchema, args, "local_mark_operation input");
881
+ const result = await local_mark_operation(validated);
882
+ return {
883
+ content: [{ type: "text", text: JSON.stringify(result) }],
884
+ structuredContent: {
885
+ result: {
886
+ status: "success",
887
+ data: result,
888
+ },
889
+ },
890
+ };
891
+ }
892
+ catch (error) {
893
+ const errorMessage = error instanceof Error ? error.message : String(error);
894
+ return {
895
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
896
+ structuredContent: {
897
+ result: {
898
+ status: "error",
899
+ error: errorMessage,
900
+ },
901
+ },
902
+ };
903
+ }
904
+ }
905
+ async function handleInfoOperation(args) {
906
+ try {
907
+ const validated = strictParse(LocalInfoOperationSchema, args, "local_info_operation input");
908
+ const result = await local_info_operation(validated);
909
+ return {
910
+ content: [{ type: "text", text: JSON.stringify(result) }],
911
+ structuredContent: {
912
+ result: {
913
+ status: "success",
914
+ data: result,
915
+ },
916
+ },
917
+ };
918
+ }
919
+ catch (error) {
920
+ const errorMessage = error instanceof Error ? error.message : String(error);
921
+ return {
922
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
923
+ structuredContent: {
924
+ result: {
925
+ status: "error",
926
+ error: errorMessage,
927
+ },
928
+ },
929
+ };
930
+ }
931
+ }
932
+ async function handleWipOperations(args) {
933
+ const validated = strictParse(WipOperationsSchema, args, "wip_file input");
934
+ let structuredContent;
935
+ switch (validated.type) {
936
+ case "generate": {
937
+ const result = await generate_wip(validated.options, validated.outputPath);
938
+ structuredContent = { result: { type: "generate", filePath: result } };
939
+ break;
940
+ }
941
+ case "verify": {
942
+ const result = await verify_wip(validated.wipFilePath, validated.hash_equal, validated.requireSignature);
943
+ structuredContent = { result: { type: "verify", ...result } };
944
+ break;
945
+ }
946
+ case "sign": {
947
+ const result = await sign_wip(validated.wipFilePath, validated.account, validated.outputPath);
948
+ structuredContent = { result: { type: "sign", filePath: result } };
949
+ break;
950
+ }
951
+ case "wip2html": {
952
+ const result = await wip2html(validated.wipPath, validated.options);
953
+ let output = { type: "wip2html" };
954
+ if (typeof result === "string") {
955
+ output.html = result;
956
+ }
957
+ else if (Array.isArray(result)) {
958
+ output.files = result;
959
+ }
960
+ else {
961
+ output.html = String(result);
962
+ }
963
+ structuredContent = { result: output };
964
+ break;
965
+ }
966
+ default:
967
+ throw new Error("Unknown WIP operation type");
968
+ }
969
+ return {
970
+ content: [{ type: "text", text: JSON.stringify(structuredContent) }],
971
+ structuredContent,
972
+ };
973
+ }
974
+ async function handleWatchQueryOperations(args) {
975
+ const validated = strictParse(WatchQueryOperationsSchema, args, "watch_and_query input");
976
+ let result;
977
+ switch (validated.query_type) {
978
+ case "local_mark_list": {
979
+ const queryResult = await query_local_mark_list(validated.filter || {});
980
+ result = { query_type: "local_mark_list", result: queryResult };
981
+ break;
982
+ }
983
+ case "account_list": {
984
+ const queryResult = await query_account_list(validated.filter);
985
+ result = { query_type: "account_list", result: queryResult };
986
+ break;
987
+ }
988
+ case "local_info_list": {
989
+ const queryResult = await query_local_info_list(validated.filter);
990
+ result = { query_type: "local_info_list", result: queryResult };
991
+ break;
992
+ }
993
+ case "token_list": {
994
+ const queryResult = await query_local_token_list(validated.filter || {});
995
+ result = { query_type: "token_list", result: queryResult };
996
+ break;
997
+ }
998
+ case "account_balance": {
999
+ const queryResult = await query_account({ name_or_address: validated.name_or_address, token_type: validated.token_type, balance: validated.balance, coin: validated.coin, network: validated.network });
1000
+ result = { query_type: "account_balance", result: queryResult };
1001
+ break;
1002
+ }
1003
+ case "onchain_personal_profile": {
1004
+ const queryResult = await query_personal({ account: validated.account, no_cache: validated.no_cache, network: validated.network });
1005
+ result = { query_type: "onchain_personal_profile", result: queryResult };
1006
+ break;
1007
+ }
1008
+ case "onchain_objects": {
1009
+ const queryResult = await query_objects({ objects: validated.objects, no_cache: validated.no_cache, network: validated.network });
1010
+ if (queryResult && queryResult.objects && Array.isArray(queryResult.objects)) {
1011
+ queryResult.objects = queryResult.objects.map((obj) => {
1012
+ if (obj && obj.data && obj.data.type === "Guard" && obj.data.root) {
1013
+ try {
1014
+ const nodeComments = generateNodeComments(obj.data.root);
1015
+ return {
1016
+ ...obj,
1017
+ _guard_node_comments: nodeComments
1018
+ };
1019
+ }
1020
+ catch (e) {
1021
+ return obj;
1022
+ }
1023
+ }
1024
+ return obj;
1025
+ });
1026
+ }
1027
+ result = { query_type: "onchain_objects", result: queryResult };
1028
+ break;
1029
+ }
1030
+ case "onchain_received": {
1031
+ const queryResult = await query_received({
1032
+ name_or_address: normalizeAccountOrMark(validated.name_or_address),
1033
+ all_type: validated.all_type,
1034
+ cursor: validated.cursor,
1035
+ limit: validated.limit,
1036
+ no_cache: validated.no_cache,
1037
+ network: validated.network
1038
+ });
1039
+ result = { query_type: "onchain_received", result: queryResult };
1040
+ break;
1041
+ }
1042
+ default:
1043
+ throw new Error(`Unknown query type. Valid query_types are: "local_mark_list", "account_list", "local_info_list", "token_list", "account_balance", "onchain_personal_profile", "onchain_objects", "onchain_received". For table queries, use the "onchain_table_data" tool.`);
1044
+ }
1045
+ return {
1046
+ content: [{ type: "text", text: JSON.stringify({ result }) }],
1047
+ structuredContent: { result },
1048
+ };
1049
+ }
1050
+ async function handleWowokInfo(args) {
1051
+ const validated = strictParse(ProtocolInfoQuerySchema, args, "wowok_buildin_info input");
1052
+ const queryResult = await queryProtocolInfo(validated);
1053
+ return {
1054
+ content: [{ type: "text", text: JSON.stringify({ result: queryResult }) }],
1055
+ structuredContent: { result: queryResult },
1056
+ };
1057
+ }
1058
+ async function handleOnchainEvents(args) {
1059
+ const validated = strictParse(OnchainEventsInputSchema, args, "onchain_events input");
1060
+ const queryResult = await query_events({
1061
+ type: validated.type,
1062
+ cursor: validated.cursor ?? null,
1063
+ limit: validated.limit ?? null,
1064
+ order: validated.order ?? null,
1065
+ no_cache: validated.no_cache,
1066
+ network: validated.network,
1067
+ });
1068
+ return {
1069
+ content: [{ type: "text", text: JSON.stringify({ result: queryResult }) }],
1070
+ structuredContent: { result: queryResult },
1071
+ };
1072
+ }
1073
+ function normalizeAccountOrMark(input) {
1074
+ if (typeof input === 'string') {
1075
+ return { name_or_address: input, local_mark_first: true };
1076
+ }
1077
+ return input;
1078
+ }
1079
+ function normalizeManyAccountOrMark(input) {
1080
+ if (Array.isArray(input)) {
1081
+ return {
1082
+ entities: input.map(item => typeof item === 'string' ? { name_or_address: item, local_mark_first: true } : item),
1083
+ check_all_founded: true
1084
+ };
1085
+ }
1086
+ return input;
1087
+ }
1088
+ async function handleMessengerOperation(args) {
1089
+ const validated = strictParse(MessengerOperationInputSchema, args, "messenger_operation input");
1090
+ let result;
1091
+ switch (validated.operation) {
1092
+ case "watch_conversations": {
1093
+ const conversations = await watch_conversations(validated.filter);
1094
+ result = { operation: "watch_conversations", result: conversations };
1095
+ break;
1096
+ }
1097
+ case "send_message": {
1098
+ const sendResult = await send_message(validated.from, normalizeAccountOrMark(validated.to), validated.content, validated.options);
1099
+ const filteredResult = {
1100
+ ...sendResult,
1101
+ merkleData: sendResult.merkleData ? {
1102
+ leafIndex: sendResult.merkleData.leafIndex,
1103
+ prevRoot: sendResult.merkleData.prevRoot,
1104
+ newRoot: sendResult.merkleData.newRoot,
1105
+ serverSignature: sendResult.merkleData.serverSignature,
1106
+ serverTimestamp: sendResult.merkleData.serverTimestamp,
1107
+ serverPublicKey: sendResult.merkleData.serverPublicKey,
1108
+ } : undefined,
1109
+ };
1110
+ result = { operation: "send_message", result: filteredResult };
1111
+ break;
1112
+ }
1113
+ case "send_file": {
1114
+ const sendResult = await send_file(validated.from, normalizeAccountOrMark(validated.to), validated.filePath, validated.options);
1115
+ const filteredResult = {
1116
+ ...sendResult,
1117
+ merkleData: sendResult.merkleData ? {
1118
+ leafIndex: sendResult.merkleData.leafIndex,
1119
+ prevRoot: sendResult.merkleData.prevRoot,
1120
+ newRoot: sendResult.merkleData.newRoot,
1121
+ serverSignature: sendResult.merkleData.serverSignature,
1122
+ serverTimestamp: sendResult.merkleData.serverTimestamp,
1123
+ serverPublicKey: sendResult.merkleData.serverPublicKey,
1124
+ } : undefined,
1125
+ };
1126
+ result = { operation: "send_file", result: filteredResult };
1127
+ break;
1128
+ }
1129
+ case "watch_messages": {
1130
+ const filter = validated.filter ? {
1131
+ ...validated.filter,
1132
+ peerAddress: validated.filter.peerAddress ? normalizeAccountOrMark(validated.filter.peerAddress) : undefined
1133
+ } : undefined;
1134
+ const messages = await watch_messages(filter);
1135
+ result = { operation: "watch_messages", result: messages };
1136
+ break;
1137
+ }
1138
+ case "extract_zip_messages": {
1139
+ const extractedPaths = await extract_zip_messages(validated.account, validated.messages, validated.outputDir);
1140
+ result = { operation: "extract_zip_messages", result: extractedPaths };
1141
+ break;
1142
+ }
1143
+ case "generate_wts": {
1144
+ const params = validated.params ? {
1145
+ ...validated.params,
1146
+ peerAccount: normalizeAccountOrMark(validated.params.peerAccount)
1147
+ } : undefined;
1148
+ const wtsResult = await generate_wts(params);
1149
+ result = { operation: "generate_wts", result: wtsResult };
1150
+ break;
1151
+ }
1152
+ case "verify_wts": {
1153
+ const verifyResult = await verify_wts(validated.wtsFilePath);
1154
+ result = { operation: "verify_wts", result: verifyResult };
1155
+ break;
1156
+ }
1157
+ case "sign_wts": {
1158
+ const signedPath = await sign_wts(validated.wtsFilePath, validated.account, validated.outputPath);
1159
+ result = { operation: "sign_wts", result: signedPath };
1160
+ break;
1161
+ }
1162
+ case "wts2html": {
1163
+ const htmlResult = await wts2html(validated.wtsPath, validated.options);
1164
+ result = { operation: "wts2html", result: htmlResult };
1165
+ break;
1166
+ }
1167
+ case "proof_message": {
1168
+ const proofResult = await proof_message(validated.account, validated.messageId, validated.network);
1169
+ result = { operation: "proof_message", result: proofResult };
1170
+ break;
1171
+ }
1172
+ case "blacklist": {
1173
+ const blacklistParams = {
1174
+ account: validated.account,
1175
+ op: validated.blacklist.op
1176
+ };
1177
+ if ('users' in validated.blacklist) {
1178
+ blacklistParams.users = normalizeManyAccountOrMark(validated.blacklist.users);
1179
+ }
1180
+ const blacklistResult = await blacklist(blacklistParams);
1181
+ result = { operation: "blacklist", op: validated.blacklist.op, result: blacklistResult.result };
1182
+ break;
1183
+ }
1184
+ case "friendslist": {
1185
+ const friendslistParams = {
1186
+ account: validated.account,
1187
+ op: validated.friendslist.op
1188
+ };
1189
+ if ('users' in validated.friendslist) {
1190
+ friendslistParams.users = normalizeManyAccountOrMark(validated.friendslist.users);
1191
+ }
1192
+ const friendslistResult = await friendslist(friendslistParams);
1193
+ result = { operation: "friendslist", op: validated.friendslist.op, result: friendslistResult.result };
1194
+ break;
1195
+ }
1196
+ case "guardlist": {
1197
+ const guardlistResult = await guardlist({
1198
+ account: validated.account,
1199
+ ...validated.guardlist
1200
+ });
1201
+ result = { operation: "guardlist", op: validated.guardlist.op, result: guardlistResult.result };
1202
+ break;
1203
+ }
1204
+ case "settings": {
1205
+ const settingsResult = await settings({
1206
+ account: validated.account,
1207
+ ...validated.settings
1208
+ });
1209
+ result = { operation: "settings", op: validated.settings.op, result: settingsResult.result };
1210
+ break;
1211
+ }
1212
+ case "mark_messages_as_viewed": {
1213
+ const markedCount = await mark_messages_as_viewed(validated.messageIds, validated.account);
1214
+ result = { operation: "mark_messages_as_viewed", result: markedCount };
1215
+ break;
1216
+ }
1217
+ case "mark_conversation_as_viewed": {
1218
+ const markedCount = await mark_conversation_as_viewed(normalizeAccountOrMark(validated.peerAddress), validated.account);
1219
+ result = { operation: "mark_conversation_as_viewed", result: markedCount };
1220
+ break;
1221
+ }
1222
+ default:
1223
+ throw new Error(`Unknown messenger operation: ${validated.operation}`);
1224
+ }
1225
+ return {
1226
+ content: [{ type: "text", text: JSON.stringify(result) }],
1227
+ structuredContent: { result },
1228
+ };
1229
+ }
1230
+ async function handleGuard2File(args) {
1231
+ const validated = strictParse(Guard2File_InputSchema, args, "guard2file input");
1232
+ const env = getEnvConfig(validated.env);
1233
+ try {
1234
+ await guard2file(validated.guard, validated.file_path, validated.format || "json", env.network);
1235
+ const result = {
1236
+ result: {
1237
+ status: "success",
1238
+ data: {
1239
+ file_path: resolve(validated.file_path),
1240
+ format: validated.format || "json",
1241
+ guard_object: validated.guard,
1242
+ },
1243
+ },
1244
+ };
1245
+ return {
1246
+ content: [{ type: "text", text: JSON.stringify(result) }],
1247
+ structuredContent: result,
1248
+ };
1249
+ }
1250
+ catch (error) {
1251
+ const result = {
1252
+ result: {
1253
+ status: "error",
1254
+ error: error.message,
1255
+ },
1256
+ };
1257
+ return {
1258
+ content: [{ type: "text", text: JSON.stringify(result) }],
1259
+ structuredContent: result,
1260
+ };
1261
+ }
1262
+ }
1263
+ async function handleMachineNode2File(args) {
1264
+ const validated = strictParse(MachineNode2File_InputSchema, args, "machineNode2file input");
1265
+ const env = getEnvConfig(validated.env);
1266
+ try {
1267
+ await machineNode2file(validated.machine, validated.file_path, validated.format || "json", env.network);
1268
+ const result = {
1269
+ result: {
1270
+ status: "success",
1271
+ data: {
1272
+ file_path: resolve(validated.file_path),
1273
+ format: validated.format || "json",
1274
+ machine_object: validated.machine,
1275
+ node_count: 0,
1276
+ },
1277
+ },
1278
+ };
1279
+ return {
1280
+ content: [{ type: "text", text: JSON.stringify(result) }],
1281
+ structuredContent: result,
1282
+ };
1283
+ }
1284
+ catch (error) {
1285
+ const result = {
1286
+ result: {
1287
+ status: "error",
1288
+ error: error.message,
1289
+ },
1290
+ };
1291
+ return {
1292
+ content: [{ type: "text", text: JSON.stringify(result) }],
1293
+ structuredContent: result,
1294
+ };
1295
+ }
1296
+ }
1297
+ export { OnchainOperationsSchema, WipOperationsSchema, WatchQueryOperationsSchema, AccountOperationSchema, LocalMarkOperationSchema, LocalInfoOperationSchema, ProtocolInfoQuerySchema, CallOutputSchema, MessengerOperationInputSchema, MessengerOperationOutputSchema };
1298
+ async function main() {
1299
+ server.registerTool("onchain_operations", {
1300
+ title: "⛓️ On-chain Operations",
1301
+ description: "On-chain operations for WoWok object: service (marketplace listings), machine (workflow templates), progress (order tracking), repository (on-chain database), arbitration (dispute resolution), contact (IM management), treasury (team funds), reward (incentive pools), allocation (auto-distribution), permission (access control), guard (programmable trust rules), personal (public profile), payment (direct coin transfers), demand (service requests), order (order management), gen_passport (verified credentials).",
1302
+ inputSchema: OnchainOperationsSchema,
1303
+ outputSchema: CallOutputSchema,
1304
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
1305
+ _meta: createToolMeta("operation", ["service", "machine", "progress", "repository", "arbitration", "contact", "treasury", "reward", "allocation", "permission", "guard", "personal", "payment", "demand", "order", "gen_passport", "on-chain", "blockchain"]),
1306
+ }, handleOnchainOperations);
1307
+ server.registerTool("account_operation", {
1308
+ title: "πŸ”’ LOCAL ONLY: Account - Wallet Management",
1309
+ description: "πŸ”’ 100% LOCAL, NEVER ON-CHAIN πŸ”’ Manage WoWok accounts locally on device: generate, suspend, resume, faucet-test, operate assets, sign data, etc.",
1310
+ inputSchema: AccountOperationSchema,
1311
+ outputSchema: AccountOperationOutputWrappedSchema,
1312
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
1313
+ _meta: createToolMeta("operation", ["account", "local", "private", "wallet", "off-chain"]),
1314
+ }, handleAccountOperation);
1315
+ server.registerTool("local_mark_operation", {
1316
+ title: "πŸ”’ LOCAL ONLY: LocalMark - Address Book Management",
1317
+ description: "100% LOCAL, NEVER ON-CHAIN πŸ”’ Manage ID names and tags stored ONLY on your local device for easy identification of user address or object IDs by name.",
1318
+ inputSchema: LocalMarkOperationSchema,
1319
+ outputSchema: LocalMarkOperationOutputWrappedSchema,
1320
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
1321
+ _meta: createToolMeta("operation", ["mark", "local", "private", "address-book", "off-chain"]),
1322
+ }, handleMarkOperation);
1323
+ server.registerTool("local_info_operation", {
1324
+ title: "πŸ”’ LOCAL ONLY: LocalInfo - Private Data Management",
1325
+ description: "100% LOCAL, NEVER ON-CHAIN πŸ”’ Manage sensitive personal information stored ONLY on your device: delivery addresses, phone numbers, contacts.",
1326
+ inputSchema: LocalInfoOperationSchema,
1327
+ outputSchema: LocalInfoOperationOutputWrappedSchema,
1328
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
1329
+ _meta: createToolMeta("operation", ["info", "local", "private", "data-management", "off-chain"]),
1330
+ }, handleInfoOperation);
1331
+ server.registerTool("wip_file", {
1332
+ title: "🀝 Witness Information Promise File Operations",
1333
+ description: "generate (create WIP files from markdown and images), verify (integrity check), sign (add signatures), or wip2html (convert to HTML).",
1334
+ inputSchema: WipOperationsSchema,
1335
+ outputSchema: z.object({
1336
+ result: WipOperationOutputSchema,
1337
+ }),
1338
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
1339
+ _meta: createToolMeta("operation", ["wip", "promise", "file-generation", "verification", "signature", "local"]),
1340
+ }, handleWipOperations);
1341
+ server.registerTool("messenger_operation", {
1342
+ title: "πŸ’¬ Messenger Operations",
1343
+ description: "WoWok encrypted messenger operations: watch conversations (with unread filtering, preview messages), send message, send file, watch messages (with viewed status filtering), extract zip messages, generate WTS, verify WTS, sign WTS, WTS to HTML, proof message on-chain, manage blacklist, friendslist, guardlist, settings, mark messages as viewed, and mark conversation as viewed.",
1344
+ inputSchema: MessengerOperationInputSchema,
1345
+ outputSchema: MessengerOperationOutputSchema,
1346
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
1347
+ _meta: createToolMeta("operation", ["messenger", "message", "file", "wts", "blacklist", "friendslist", "guardlist", "settings", "proof", "communication"]),
1348
+ }, handleMessengerOperation);
1349
+ server.registerTool("guard2file", {
1350
+ title: "πŸ“„ Guard to File - Export Guard Definition",
1351
+ description: "Export a Guard object's definition from the blockchain to a local JSON or Markdown file for editing and creating new Guard objects. Note: To query on-chain object information, use the 'query_toolkit' tool instead.",
1352
+ inputSchema: Guard2File_InputSchema,
1353
+ outputSchema: Guard2File_OutputWrappedSchema,
1354
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1355
+ _meta: createToolMeta("generate file", ["guard", "export", "file", "json", "markdown", "on-chain"]),
1356
+ }, handleGuard2File);
1357
+ server.registerTool("machineNode2file", {
1358
+ title: "βš™οΈ Machine Node to File - Export Machine Node Definition",
1359
+ description: "Export a Machine object's node definition from the blockchain to a local JSON or Markdown file for editing and creating new Machine objects. Note: To query on-chain object information, use the 'query_toolkit' tool instead.",
1360
+ inputSchema: MachineNode2File_InputSchema,
1361
+ outputSchema: MachineNode2File_OutputWrappedSchema,
1362
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1363
+ _meta: createToolMeta("generate file", ["machine", "export", "file", "json", "markdown", "on-chain", "workflow"]),
1364
+ }, handleMachineNode2File);
1365
+ server.registerTool("query_toolkit", {
1366
+ title: "πŸ” Data Query Toolkit",
1367
+ description: "WOWOK data query toolkit β€” 8 query types covering local device data and on-chain blockchain data:\n\n"
1368
+ + "LOCAL (device-only, never on-chain):\n"
1369
+ + "1. local_mark_list — Query your LOCAL address book: maps human-readable names to blockchain addresses with optional tags. Use to resolve names→addresses or find addresses by tag.\n"
1370
+ + "2. account_list β€” Query your LOCAL accounts: view all accounts stored on this device (addresses, public keys, messenger status, suspension state). Use to discover available accounts before operations.\n"
1371
+ + "3. local_info_list β€” Query your LOCAL private info: sensitive data like delivery addresses, phone numbers, contacts stored ONLY on this device.\n"
1372
+ + "4. token_list β€” Query cached token metadata: symbol, decimals, icon URL, description for tokens previously fetched from chain. Use to look up token precision/decimals before performing token operations. Returns: TokenTypeInfo[] (type, alias, name, symbol, decimals, iconUrl).\n"
1373
+ + "5. account_balance β€” Query an account's coin balance OR paginated coin objects. Use balance=true for total amount, or coin={cursor,limit} to list individual coin objects. Supports multi-token via token_type parameter.\n\n"
1374
+ + "ONCHAIN (blockchain):\n"
1375
+ + "6. onchain_personal_profile β€” Query any user's PUBLIC on-chain profile: social links, reputation (likes/dislikes), personal info records, voting history, referrer.\n"
1376
+ + "7. onchain_objects β€” Batch query on-chain WOWOK objects by ID or name: supports Service, Machine, Order, Treasury, Reward, Arb, Personal, Contact, and more.\n"
1377
+ + "8. onchain_received β€” Query objects (Payments, Tokens, NFTs) received by a specific object. Supports pagination and all_type filter.\n\n"
1378
+ + "For dynamic table data queries (pagination, table items), use the 'onchain_table_data' tool.",
1379
+ inputSchema: WatchQueryOperationsSchema,
1380
+ outputSchema: z.object({
1381
+ result: z.any().describe("Query result β€” type depends on query_type. Local queries return arrays (MarkData[], AccountData[], InfoData[], TokenTypeInfo[]). account_balance returns { address, balance? | coin? }. Onchain queries return typed objects or undefined. onchain_received returns ReceivedBalance | ReceivedNormal[].")
1382
+ }),
1383
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1384
+ _meta: createToolMeta("query", ["watch", "query", "on-chain", "local", "events", "objects", "tokens", "balance", "profile"]),
1385
+ }, handleWatchQueryOperations);
1386
+ server.registerTool("onchain_table_data", {
1387
+ title: "πŸ“Š Watch WoWok On-chain Table Data Query",
1388
+ description: "Query dynamic table data of on-chain objects β€” supports paginated table queries and specific table item lookups. Each table item belongs to a parent object type and has a specific meaning:\n\n"
1389
+ + "1. onchain_table β€” Paginated query of ANY object's dynamic fields table (Parent: any object). Returns all entries with keys, types, and object IDs. Use to explore all sub-items of an object.\n"
1390
+ + "2. onchain_table_item_repository_data β€” Query a record from a Repository's on-chain key-value database (Parent: Repository). Key: name + entity (address or number). Returns the stored data record with typed value.\n"
1391
+ + "3. onchain_table_item_permission_perm β€” Query a permission entry from a Permission object's access control table (Parent: Permission). Key: user address or Guard ID. Returns the permission list (perm[]) granted to that user/guard.\n"
1392
+ + "4. onchain_table_item_entity_registrar β€” Query an entity's registration record from the GLOBAL EntityRegistrar (Parent: system EntityRegistrar). Key: user address. Returns registration info: description, referrer, records, mark_object.\n"
1393
+ + "5. onchain_table_item_entity_linker β€” Query community votes/endorsements for an entity from the GLOBAL EntityLinker (Parent: system EntityLinker). Key: entity address. Returns vote records (likes/dislikes) showing community trust.\n"
1394
+ + "6. onchain_table_item_reward_record β€” Query a reward claim record from a Reward object's distribution table (Parent: Reward). Key: recipient address. Returns claim history: guard used, total claimed, per-claim details.\n"
1395
+ + "7. onchain_table_item_demand_presenter β€” Query a demand submission from a Demand object's presenter table (Parent: Demand). Key: presenter address. Returns submission details: recommendation, service, feedback, acceptance score.\n"
1396
+ + "8. onchain_table_item_treasury_history β€” Query a payment record from a Treasury's history table (Parent: Treasury). Key: payment ID (address). Returns payment details: operation type, signer, amount, external guard.\n"
1397
+ + "9. onchain_table_item_machine_node β€” Query a workflow node definition from a Machine object's node table (Parent: Machine). Key: node name (string). Returns node configuration: pairs, forwards, guards, thresholds.\n"
1398
+ + "10. onchain_table_item_progress_history β€” Query a progress step record from a Progress object's history table (Parent: Progress). Key: sequence number (u64). Returns step details: node, next_node, session state, time.\n"
1399
+ + "11. onchain_table_item_address_mark β€” Query a PUBLIC on-chain name/tag mark from an AddressMark object's table (Parent: AddressMark). Key: address. Returns public labels: entity, name, tags[]. Unlike local marks, these are published on-chain.\n"
1400
+ + "12. onchain_table_item_generic β€” Query a generic table item from ANY object's dynamic fields (Parent: any object). Supports arbitrary key types (address, u64, string, object ID, etc.). Use for custom objects and general-purpose table lookups. Returns: ObjectBase | undefined.",
1401
+ inputSchema: OnchainTableDataSchema,
1402
+ outputSchema: OnchainTableDataResultSchema,
1403
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1404
+ _meta: createToolMeta("table query", ["on-chain", "table", "dynamic fields", "pagination", "repository", "permission", "reward", "demand", "treasury", "machine", "progress"]),
1405
+ }, handleOnchainTableData);
1406
+ server.registerTool("onchain_events", {
1407
+ title: "πŸ“… Watch WoWok On-chain Events",
1408
+ description: "Watch on-chain WoWok events by type. Supports arbitration events, new order events, progress events, demand presentation events, demand feedback events, and new entity registration events. Use pagination cursor for fetching large result sets.",
1409
+ inputSchema: OnchainEventsInputSchema,
1410
+ outputSchema: OnchainEventsResultSchema,
1411
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1412
+ _meta: createToolMeta("watch wowook events", ["events", "on-chain", "arbitration", "order", "progress", "demand", "entity"]),
1413
+ }, handleOnchainEvents);
1414
+ server.registerTool("wowok_buildin_info", {
1415
+ title: "ℹ️ WoWok Build-in Information",
1416
+ description: "Query WoWok protocol information: 'constants', 'built-in permissions', 'guard instructions', 'current network', or 'value types'.",
1417
+ inputSchema: ProtocolInfoQuerySchema,
1418
+ outputSchema: ProtocolInfoResultSchema,
1419
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1420
+ _meta: createToolMeta("WoWok info", ["build-in", "constants", "permissions", "guard", "network", "value-types"]),
1421
+ }, handleWowokInfo);
1422
+ server.registerTool("documents_and_learn", {
1423
+ title: "πŸ“š Documents and Learn",
1424
+ description: "Access WoWok documentation and learning resources. Provides official documentation URL for users and AI to get more information about WoWok protocol, components, and usage.",
1425
+ inputSchema: z.object({
1426
+ topic: z.string().optional().describe("Optional topic to search for in documentation (e.g., 'guard', 'service', 'messenger', 'stage-01-introduction')"),
1427
+ }),
1428
+ outputSchema: z.object({
1429
+ documentation_url: z.string().describe("Official WoWok documentation URL on GitHub"),
1430
+ topic: z.string().optional().describe("Requested topic if specified"),
1431
+ original_topic: z.string().optional().describe("Original topic input by user (before normalization)"),
1432
+ message: z.string().describe("Welcome message with documentation information. Always included in response."),
1433
+ }),
1434
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
1435
+ _meta: createToolMeta("documentation", ["docs", "learn", "tutorial", "guide", "help", "reference"]),
1436
+ }, async (args) => {
1437
+ const GITHUB_BASE_URL = "https://github.com/wowok-ai/docs/blob/main/docs";
1438
+ if (!args.topic) {
1439
+ const url = GITHUB_BASE_URL;
1440
+ const message = `Welcome to WoWok Documentation! Access comprehensive guides, tutorials, and API references at: ${url}`;
1441
+ return {
1442
+ content: [
1443
+ {
1444
+ type: "text",
1445
+ text: message,
1446
+ },
1447
+ ],
1448
+ structuredContent: {
1449
+ documentation_url: url,
1450
+ message: message,
1451
+ },
1452
+ };
1453
+ }
1454
+ const normalizedTopic = args.topic.toLowerCase().trim();
1455
+ const url = `${GITHUB_BASE_URL}/${normalizedTopic}.md`;
1456
+ const message = `Documentation for "${normalizedTopic}"\nGitHub URL: ${url}`;
1457
+ return {
1458
+ content: [
1459
+ {
1460
+ type: "text",
1461
+ text: message,
1462
+ },
1463
+ ],
1464
+ structuredContent: {
1465
+ documentation_url: url,
1466
+ topic: normalizedTopic,
1467
+ original_topic: args.topic,
1468
+ message: message,
1469
+ },
1470
+ };
1471
+ });
1472
+ const transport = new StdioServerTransport();
1473
+ await server.connect(transport);
1474
+ process.on("SIGINT", async () => {
1475
+ await server.close();
1476
+ process.exit(0);
1477
+ });
1478
+ }
1479
+ main().catch(console.error);