@wowok/agent-mcp 2.5.1 → 2.5.3

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 (107) hide show
  1. package/dist/index.js +46 -6
  2. package/dist/knowledge/guard-design-patterns.js +104 -1
  3. package/dist/knowledge/guard-ledger.js +3 -3
  4. package/dist/knowledge/guard-lint.js +3 -3
  5. package/dist/knowledge/guard-risk.js +23 -15
  6. package/dist/knowledge/guard-templates.js +174 -2
  7. package/dist/knowledge/guard-translation.js +3 -3
  8. package/dist/knowledge/index.d.ts +3 -0
  9. package/dist/knowledge/index.js +9 -0
  10. package/dist/knowledge/machine-context.d.ts +1 -1
  11. package/dist/knowledge/machine-context.js +21 -0
  12. package/dist/knowledge/machine-ledger.d.ts +1 -0
  13. package/dist/knowledge/machine-ledger.js +31 -11
  14. package/dist/knowledge/machine-templates.js +32 -78
  15. package/dist/knowledge/mcp-schema-audit.js +3 -2
  16. package/dist/knowledge/overrides-loader.d.ts +13 -0
  17. package/dist/knowledge/overrides-loader.js +67 -0
  18. package/dist/knowledge/payment-risk.d.ts +4 -0
  19. package/dist/knowledge/payment-risk.js +67 -0
  20. package/dist/knowledge/repository-confirm.d.ts +4 -0
  21. package/dist/knowledge/repository-confirm.js +44 -0
  22. package/dist/knowledge/repository-risk.d.ts +8 -2
  23. package/dist/knowledge/repository-risk.js +61 -0
  24. package/dist/knowledge/repository-translation.js +23 -0
  25. package/dist/knowledge/scenario-modes.js +22 -5
  26. package/dist/knowledge/service-templates.js +38 -0
  27. package/dist/knowledge/treasury-templates.js +42 -0
  28. package/dist/loop-engineering/context-collect.d.ts +7 -0
  29. package/dist/loop-engineering/context-collect.js +83 -0
  30. package/dist/loop-engineering/improve.d.ts +29 -0
  31. package/dist/loop-engineering/improve.js +178 -0
  32. package/dist/project/business-puzzle.d.ts +1 -0
  33. package/dist/project/business-puzzle.js +11 -0
  34. package/dist/project/context-assembly.d.ts +16 -0
  35. package/dist/project/context-assembly.js +130 -0
  36. package/dist/project/deployment-doc.d.ts +126 -0
  37. package/dist/project/deployment-doc.js +632 -0
  38. package/dist/project/index.d.ts +25 -0
  39. package/dist/project/index.js +78 -0
  40. package/dist/project/migration.d.ts +22 -0
  41. package/dist/project/migration.js +125 -0
  42. package/dist/project/project-store.d.ts +110 -0
  43. package/dist/project/project-store.js +425 -0
  44. package/dist/project/risk-aggregator.d.ts +7 -0
  45. package/dist/project/risk-aggregator.js +15 -0
  46. package/dist/project/rollback-policy.d.ts +45 -0
  47. package/dist/project/rollback-policy.js +290 -0
  48. package/dist/project/stage-gate.d.ts +49 -0
  49. package/dist/project/stage-gate.js +310 -0
  50. package/dist/schema/call/allocation.d.ts +5 -0
  51. package/dist/schema/call/arbitration.d.ts +5 -0
  52. package/dist/schema/call/base.d.ts +3 -0
  53. package/dist/schema/call/base.js +3 -2
  54. package/dist/schema/call/bridge.d.ts +24 -0
  55. package/dist/schema/call/contact.d.ts +5 -0
  56. package/dist/schema/call/demand.d.ts +5 -0
  57. package/dist/schema/call/guard.d.ts +15 -0
  58. package/dist/schema/call/machine.d.ts +10 -0
  59. package/dist/schema/call/order.d.ts +5 -0
  60. package/dist/schema/call/payment.d.ts +5 -0
  61. package/dist/schema/call/permission.d.ts +5 -0
  62. package/dist/schema/call/personal.d.ts +5 -0
  63. package/dist/schema/call/progress.d.ts +5 -0
  64. package/dist/schema/call/proof.d.ts +10 -0
  65. package/dist/schema/call/repository.d.ts +5 -0
  66. package/dist/schema/call/reward.d.ts +5 -0
  67. package/dist/schema/call/service.d.ts +5 -0
  68. package/dist/schema/call/treasury.d.ts +5 -0
  69. package/dist/schema/operations.d.ts +210 -0
  70. package/dist/schema/operations.js +24 -0
  71. package/dist/schema/project/index.d.ts +2798 -85
  72. package/dist/schema/project/index.js +667 -2
  73. package/dist/schema/query/index.d.ts +601 -0
  74. package/dist/schema/query/index.js +61 -0
  75. package/dist/schemas/bridge_operation.schema.json +4 -0
  76. package/dist/schemas/guard2file.schema.json +4 -0
  77. package/dist/schemas/index.json +1 -1
  78. package/dist/schemas/machineNode2file.schema.json +4 -0
  79. package/dist/schemas/onchain_operations.schema.json +20 -0
  80. package/dist/schemas/onchain_operations_allocation.schema.json +4 -0
  81. package/dist/schemas/onchain_operations_arbitration.schema.json +4 -0
  82. package/dist/schemas/onchain_operations_contact.schema.json +4 -0
  83. package/dist/schemas/onchain_operations_demand.schema.json +4 -0
  84. package/dist/schemas/onchain_operations_gen_passport.schema.json +8 -0
  85. package/dist/schemas/onchain_operations_gen_proof.schema.json +8 -0
  86. package/dist/schemas/onchain_operations_guard.schema.json +4 -577
  87. package/dist/schemas/onchain_operations_machine.schema.json +4 -0
  88. package/dist/schemas/onchain_operations_order.schema.json +4 -0
  89. package/dist/schemas/onchain_operations_payment.schema.json +4 -0
  90. package/dist/schemas/onchain_operations_permission.schema.json +4 -0
  91. package/dist/schemas/onchain_operations_personal.schema.json +4 -0
  92. package/dist/schemas/onchain_operations_progress.schema.json +4 -0
  93. package/dist/schemas/onchain_operations_proof.schema.json +4 -0
  94. package/dist/schemas/onchain_operations_repository.schema.json +4 -0
  95. package/dist/schemas/onchain_operations_reward.schema.json +4 -0
  96. package/dist/schemas/onchain_operations_service.schema.json +4 -0
  97. package/dist/schemas/onchain_operations_treasury.schema.json +4 -0
  98. package/dist/schemas/project_operation.output.json +1955 -0
  99. package/dist/schemas/project_operation.schema.json +133 -2
  100. package/dist/schemas/query_toolkit.output.json +407 -1
  101. package/dist/schemas/query_toolkit.schema.json +132 -0
  102. package/dist/tools/handlers/project.js +788 -2
  103. package/dist/tools/handlers/query.js +38 -2
  104. package/dist/tools/index.js +346 -37
  105. package/dist/tools/wrap.js +61 -7
  106. package/package.json +2 -2
  107. package/dist/schemas/onchain_operations.output.json +0 -2819
@@ -1,5 +1,5 @@
1
1
  import { strictParse, WatchQueryOperationsSchema, OnchainTableDataSchema, OnchainEventsInputSchema, ProtocolInfoQuerySchema, } from "../../schema/index.js";
2
- import { query_local_mark_list, query_account_list, query_local_info_list, query_local_token_list, query_account, GetLocalNamesByAddresses, query_personal, query_objects, query_table, query_tableItem, queryTableItem_RepositoryData, queryTableItem_PermissionPerm, queryTableItem_RewardRecord, queryTableItem_DemandPresenter, queryTableItem_TreasuryHistory, queryTableItem_MachineNode, queryTableItem_ProgressHistory, queryTableItem_AddressMark, queryTableItem_EntityRegistrar, queryTableItem_EntityLinker, query_received, queryProtocolInfo, query_events, generateNodeComments, } from "@wowok/wowok";
2
+ import { query_local_mark_list, query_account_list, query_local_info_list, query_local_token_list, query_account, GetLocalNamesByAddresses, query_personal, query_objects, query_table, query_tableItem, queryTableItem_RepositoryData, queryTableItem_PermissionPerm, queryTableItem_RewardRecord, queryTableItem_DemandPresenter, queryTableItem_TreasuryHistory, queryTableItem_MachineNode, queryTableItem_ProgressHistory, queryTableItem_AddressMark, queryTableItem_EntityRegistrar, queryTableItem_EntityLinker, query_received, queryProtocolInfo, query_events, query_transaction, query_object_history, query_address_activity, generateNodeComments, } from "@wowok/wowok";
3
3
  import { buildDataSemantic, } from "../../schema/call/semantic.js";
4
4
  import { normalizeAccountOrMark } from "./messenger.js";
5
5
  export async function handleWatchQueryOperations(args) {
@@ -89,8 +89,44 @@ export async function handleWatchQueryOperations(args) {
89
89
  result = { query_type: "onchain_received", result: queryResult };
90
90
  break;
91
91
  }
92
+ case "onchain_transaction": {
93
+ const queryResult = await query_transaction({
94
+ digest: validated.digest,
95
+ no_cache: validated.no_cache,
96
+ network: validated.network,
97
+ });
98
+ result = { query_type: "onchain_transaction", result: queryResult };
99
+ break;
100
+ }
101
+ case "onchain_object_history": {
102
+ const queryResult = await query_object_history({
103
+ object: validated.object,
104
+ cursor: validated.cursor,
105
+ limit: validated.limit,
106
+ order: validated.order,
107
+ no_cache: validated.no_cache,
108
+ network: validated.network,
109
+ });
110
+ result = { query_type: "onchain_object_history", result: queryResult };
111
+ break;
112
+ }
113
+ case "onchain_address_activity": {
114
+ const addrInput = typeof validated.name_or_address === 'string'
115
+ ? validated.name_or_address
116
+ : validated.name_or_address.name_or_address;
117
+ const queryResult = await query_address_activity({
118
+ name_or_address: addrInput,
119
+ cursor: validated.cursor,
120
+ limit: validated.limit,
121
+ order: validated.order,
122
+ no_cache: validated.no_cache,
123
+ network: validated.network,
124
+ });
125
+ result = { query_type: "onchain_address_activity", result: queryResult };
126
+ break;
127
+ }
92
128
  default:
93
- throw new Error(`Unknown query type. Valid query_types are: "local_mark_list", "account_list", "local_info_list", "token_list", "account_balance", "local_names", "onchain_personal_profile", "onchain_objects", "onchain_received". For table queries, use the "onchain_table_data" tool.`);
129
+ throw new Error(`Unknown query type. Valid query_types are: "local_mark_list", "account_list", "local_info_list", "token_list", "account_balance", "local_names", "onchain_personal_profile", "onchain_objects", "onchain_received", "onchain_transaction", "onchain_object_history", "onchain_address_activity". For table queries, use the "onchain_table_data" tool.`);
94
130
  }
95
131
  return {
96
132
  content: [{ type: "text", text: JSON.stringify({ result }) }],
@@ -286,6 +286,10 @@ export const TOOL_REGISTRY = [
286
286
  " → Input: substeps (from deployment doc), network (testnet/mainnet).\n" +
287
287
  " → Output: coherence check, D-10 substep linkage, can_proceed.\n" +
288
288
  " → Execute each substep via onchain_operations, record outcomes.\n\n" +
289
+ " Status Query (action='get_project_status')\n" +
290
+ " → Input: project, version.\n" +
291
+ " → Output: current stage (1-5), stage_name, next_action, can_proceed.\n" +
292
+ " → Call anytime to check which stage the project is in and what to do next.\n\n" +
289
293
  "Correct object creation order (topological): Permission → Allocation → Guard → Machine → Service.\n" +
290
294
  "All objects created as draft (publish=false) first; publish Machine before Service (last).\n\n" +
291
295
  "═══════════════════════════════════════════════════════════════\n" +
@@ -372,7 +376,123 @@ export const TOOL_REGISTRY = [
372
376
  },
373
377
  ];
374
378
  export const TOOL_REGISTRY_MAP = new Map(TOOL_REGISTRY.map(t => [t.name, t]));
379
+ const SUB_TOOL_NAMES = TOOL_REGISTRY.map(t => t.name);
380
+ const WowokToolRuntimeSchema = z.unknown().describe("WoWok unified tool input. Expected: { tool: \"<sub-tool>\", data: {<params>} }. " +
381
+ "Aliases accepted: tool_name→tool, args→data, name→tool, params→data. " +
382
+ "If parameters don't match the sub-tool's schema, the response includes the correct schema for self-correction.");
383
+ const WowokToolDisplaySchema = z.object({
384
+ tool: z.enum(SUB_TOOL_NAMES).optional().describe("The sub-tool to execute. Each sub-tool has its own parameter schema."),
385
+ data: z.record(z.unknown()).optional().describe("Sub-tool specific parameters. If validation fails, the response includes the correct schema for this sub-tool — read it, fix your params, and retry."),
386
+ tool_name: z.enum(SUB_TOOL_NAMES).optional().describe("DEPRECATED alias for 'tool'. Use 'tool' instead."),
387
+ args: z.record(z.unknown()).optional().describe("DEPRECATED alias for 'data'. Use 'data' instead."),
388
+ name: z.enum(SUB_TOOL_NAMES).optional().describe("DEPRECATED alias for 'tool'. Use 'tool' instead."),
389
+ params: z.record(z.unknown()).optional().describe("DEPRECATED alias for 'data'. Use 'data' instead."),
390
+ }).describe("WoWok unified tool input. Call with { tool: \"<sub-tool>\", data: {<params>} }. " +
391
+ "Aliases: tool_name/name→tool, args/params→data.");
392
+ const WOWOK_TOOL_DESCRIPTION = [
393
+ "WoWok MCP unified interface. Call with { tool: \"<sub-tool>\", data: {<params>} }.",
394
+ "",
395
+ " tool: name of the sub-tool (string)",
396
+ " data: sub-tool parameters (object)",
397
+ "",
398
+ " Aliases accepted (deprecated): tool_name/name for tool, args/params for data.",
399
+ " Inline params also accepted: { tool: \"<sub-tool>\", <param1>: ..., <param2>: ... }",
400
+ "",
401
+ " EXAMPLE: wowok({ tool: \"schema_query\", data: { action: \"get\", name: \"onchain_operations\" } })",
402
+ " EXAMPLE: wowok({ tool: \"wowok_buildin_info\", data: { info: \"mainnet bridge tokens\" } })",
403
+ " EXAMPLE (inline params): wowok({ tool: \"schema_query\", action: \"get\", name: \"onchain_operations\" })",
404
+ "",
405
+ "Available sub-tools:",
406
+ " onchain_operations — On-chain ops: service, machine, progress, repository, arbitration, etc.",
407
+ " account_operation — LOCAL wallet management (generate, suspend, faucet, sign).",
408
+ " local_mark_operation — LOCAL address book (name/tag for addresses and object IDs).",
409
+ " local_info_operation — LOCAL private data (delivery addresses, phone numbers).",
410
+ " wip_file — Work-in-progress file management.",
411
+ " messenger_operation — End-to-end encrypted messaging.",
412
+ " guard2file — Export guard rules to file.",
413
+ " machineNode2file — Export machine nodes to file.",
414
+ " query_toolkit — Query on-chain objects by ID/type/owner.",
415
+ " onchain_table_data — Query on-chain dynamic field tables with pagination.",
416
+ " onchain_events — Watch on-chain events (arbitration, order, progress, demand).",
417
+ " wowok_buildin_info — Protocol constants, built-in permissions, bridge tokens.",
418
+ " schema_query — Query JSON schemas for any sub-tool (action: list/get/get_output/search).",
419
+ " bridge_operation — Cross-chain bridge between WOW and EVM (mainnet only).",
420
+ " project_operation — 5-stage project deployment workflow (C1-C4 + graph queries).",
421
+ " config_operation — Runtime service toggles (confirm_gate, harness, etc.).",
422
+ " trust_score — Service trust/risk assessment (0-100 score, 5 dimensions).",
423
+ "",
424
+ "SCHEMA-GATED EXECUTION:",
425
+ " If your parameters don't match the sub-tool's schema, the response will include:",
426
+ " result.status = \"schema_mismatch\"",
427
+ " result.errors = specific validation errors (field path + expected type)",
428
+ " result.hint = instructions to fix and retry",
429
+ " schema.input = the correct JSON schema for the sub-tool",
430
+ " schema.tool = which sub-tool this schema belongs to",
431
+ " Read the schema, fix your params, and retry. This is normal — no need to call schema_query separately.",
432
+ "",
433
+ "SCHEMA CACHING:",
434
+ " Each sub-tool has a DIFFERENT schema. When you receive a schema in a mismatch response:",
435
+ " 1. Read the schema carefully",
436
+ " 2. Fix your parameters",
437
+ " 3. Retry the call",
438
+ " 4. CACHE the schema in your context for future calls to the SAME sub-tool",
439
+ " You should only need to see each sub-tool's schema once per conversation.",
440
+ "",
441
+ "PROJECT-BASED DEPLOYMENT (5 stages):",
442
+ " Stage 1: Project naming (provide project + version params)",
443
+ " Stage 2: project_operation action='analyze_intent' → ODG + puzzles",
444
+ " Stage 3: project_operation action='aggregate_risks' → risk findings",
445
+ " Stage 4: project_operation action='generate_deployment_doc' → deployment doc",
446
+ " Stage 5: project_operation action='trace_substeps' → substep verification",
447
+ " Status: project_operation action='get_project_status' → current stage + next action",
448
+ "",
449
+ "Correct object creation order: Permission → Allocation → Guard → Machine → Service.",
450
+ "All objects created as draft (publish=false) first; publish Machine before Service (last).",
451
+ ].join("\n");
452
+ function formatZodErrors(error) {
453
+ return error.issues.map(issue => {
454
+ const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
455
+ return `${path}: ${issue.message}`;
456
+ });
457
+ }
458
+ function checkUnknownFields(schema, input) {
459
+ let innerSchema = schema;
460
+ while (true) {
461
+ const def = innerSchema._def;
462
+ if (!def || def.typeName !== "ZodEffects")
463
+ break;
464
+ innerSchema = def.schema ?? innerSchema;
465
+ }
466
+ const def = innerSchema._def;
467
+ const shape = def?.shape?.();
468
+ if (!shape || typeof input !== "object" || input === null)
469
+ return [];
470
+ const allowedFields = Object.keys(shape);
471
+ const inputFields = Object.keys(input);
472
+ return inputFields.filter(f => !allowedFields.includes(f));
473
+ }
474
+ function extractRelevantSchema(fullSchema, toolName, data) {
475
+ if (toolName === "onchain_operations" && typeof data === "object" && data !== null) {
476
+ const opType = data.operation_type;
477
+ if (typeof opType === "string") {
478
+ const subSchemaName = `onchain_operations_${opType}`;
479
+ const subSchema = loadPreGeneratedSchema(subSchemaName);
480
+ if (subSchema)
481
+ return subSchema;
482
+ }
483
+ }
484
+ return fullSchema;
485
+ }
486
+ function isSchemaValidationError(message) {
487
+ return (message.startsWith("Unknown ") && message.includes("field") ||
488
+ message.includes("expected") && message.includes("received") ||
489
+ message.includes("Invalid input") ||
490
+ message.includes("Required"));
491
+ }
375
492
  export async function dispatchToolCall(name, args, options) {
493
+ if (name === "wowok") {
494
+ return handleWowok(args);
495
+ }
376
496
  const entry = TOOL_REGISTRY_MAP.get(name);
377
497
  if (!entry) {
378
498
  throw new Error(`Unknown tool: ${name}. Available: ${TOOL_REGISTRY.map(t => t.name).join(", ")}`);
@@ -387,6 +507,206 @@ export async function dispatchToolCall(name, args, options) {
387
507
  const wrapped = wrapHandlerWithErrorShape(harnessWrapped, timeoutMs, name, entry.errorShapeBuilder);
388
508
  return wrapped(args);
389
509
  }
510
+ const TOOL_FIELD_ALIASES = ["tool", "tool_name", "name"];
511
+ const DATA_FIELD_ALIASES = ["data", "args", "params", "parameters"];
512
+ const RESERVED_FIELD_NAMES = new Set([
513
+ ...TOOL_FIELD_ALIASES,
514
+ ...DATA_FIELD_ALIASES,
515
+ ]);
516
+ function normalizeInput(args) {
517
+ const notes = [];
518
+ if (!args || typeof args !== "object" || Array.isArray(args)) {
519
+ return { tool: undefined, data: {}, normalizationNotes: ["input is not an object"] };
520
+ }
521
+ const obj = args;
522
+ let tool;
523
+ for (const alias of TOOL_FIELD_ALIASES) {
524
+ if (typeof obj[alias] === "string" && obj[alias]) {
525
+ tool = obj[alias];
526
+ if (alias !== "tool") {
527
+ notes.push(`normalized '${alias}' → 'tool'`);
528
+ }
529
+ break;
530
+ }
531
+ }
532
+ let data;
533
+ for (const alias of DATA_FIELD_ALIASES) {
534
+ const v = obj[alias];
535
+ if (v !== undefined && v !== null && typeof v === "object" && !Array.isArray(v)) {
536
+ data = v;
537
+ if (alias !== "data") {
538
+ notes.push(`normalized '${alias}' → 'data'`);
539
+ }
540
+ break;
541
+ }
542
+ }
543
+ if (!data) {
544
+ const inlineParams = {};
545
+ let hasInline = false;
546
+ for (const key of Object.keys(obj)) {
547
+ if (!RESERVED_FIELD_NAMES.has(key)) {
548
+ inlineParams[key] = obj[key];
549
+ hasInline = true;
550
+ }
551
+ }
552
+ if (hasInline) {
553
+ data = inlineParams;
554
+ notes.push("extracted inline params → 'data' (no data wrapper was provided)");
555
+ }
556
+ else {
557
+ data = {};
558
+ }
559
+ }
560
+ return { tool, data, normalizationNotes: notes };
561
+ }
562
+ async function handleWowok(args) {
563
+ const { tool: normalizedToolName, data: normalizedData, normalizationNotes } = normalizeInput(args);
564
+ if (!normalizedToolName) {
565
+ const receivedKeys = (args && typeof args === "object" && !Array.isArray(args))
566
+ ? Object.keys(args).join(", ") || "(none)"
567
+ : `(non-object input: ${typeof args})`;
568
+ const errors = [
569
+ `Missing 'tool' field. Received keys: ${receivedKeys}`,
570
+ `Expected one of: ${SUB_TOOL_NAMES.join(", ")}`,
571
+ ];
572
+ return {
573
+ content: [{
574
+ type: "text",
575
+ text: `Missing 'tool' field. Call format: wowok({ tool: "<sub-tool>", data: {<params>} }). Received keys: ${receivedKeys}. Available sub-tools: ${SUB_TOOL_NAMES.join(", ")}`,
576
+ }],
577
+ structuredContent: {
578
+ result: {
579
+ status: "schema_mismatch",
580
+ errors,
581
+ hint: `Provide 'tool' (one of: ${SUB_TOOL_NAMES.join(", ")}) and 'data' (sub-tool parameters). Aliases accepted: tool_name/name→tool, args/params→data.`,
582
+ received: args,
583
+ },
584
+ schema: {
585
+ input: zodToJsonSchemaSafe(WowokToolDisplaySchema, "wowok"),
586
+ tool: "wowok",
587
+ },
588
+ },
589
+ };
590
+ }
591
+ const entry = TOOL_REGISTRY_MAP.get(normalizedToolName);
592
+ if (!entry) {
593
+ const suggestions = TOOL_REGISTRY
594
+ .map(t => t.name)
595
+ .filter(name => name.includes(normalizedToolName) || normalizedToolName.includes(name))
596
+ .slice(0, 5);
597
+ return {
598
+ content: [{
599
+ type: "text",
600
+ text: `Unknown sub-tool: '${normalizedToolName}'. Available: ${TOOL_REGISTRY.map(t => t.name).join(", ")}${suggestions.length > 0 ? `. Did you mean: ${suggestions.join(", ")}?` : ""}`,
601
+ }],
602
+ structuredContent: {
603
+ result: {
604
+ status: "error",
605
+ errors: [`Unknown sub-tool: ${normalizedToolName}`],
606
+ hint: `Available sub-tools: ${TOOL_REGISTRY.map(t => t.name).join(", ")}${suggestions.length > 0 ? `. Did you mean: ${suggestions.join(", ")}?` : ""}`,
607
+ suggestions,
608
+ },
609
+ schema: null,
610
+ },
611
+ };
612
+ }
613
+ if (normalizationNotes.length > 0) {
614
+ console.warn(`[wowok] input normalization for '${normalizedToolName}': ${normalizationNotes.join("; ")}`);
615
+ }
616
+ const validationResult = entry.config.inputSchema.safeParse(normalizedData);
617
+ const unknownFields = checkUnknownFields(entry.config.inputSchema, normalizedData);
618
+ if (!validationResult.success || unknownFields.length > 0) {
619
+ const allErrors = [];
620
+ if (!validationResult.success) {
621
+ allErrors.push(...formatZodErrors(validationResult.error));
622
+ }
623
+ if (unknownFields.length > 0) {
624
+ allErrors.push(`Unknown field(s): ${unknownFields.join(", ")}`);
625
+ }
626
+ const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
627
+ const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
628
+ return {
629
+ content: [{
630
+ type: "text",
631
+ text: `Schema mismatch for ${normalizedToolName}. ${allErrors.length} error(s). Read the schema below, fix your params, and retry.`,
632
+ }],
633
+ structuredContent: {
634
+ result: {
635
+ status: "schema_mismatch",
636
+ errors: allErrors,
637
+ hint: `Fix your parameters based on the schema below and retry. CACHE THIS SCHEMA for future ${normalizedToolName} calls — you don't need to query it again.`,
638
+ },
639
+ schema: {
640
+ input: relevantSchema,
641
+ tool: normalizedToolName,
642
+ },
643
+ },
644
+ };
645
+ }
646
+ try {
647
+ const subResult = await dispatchToolCall(normalizedToolName, normalizedData);
648
+ const sc = subResult.structuredContent;
649
+ const resultField = sc?.result;
650
+ const isErrorResponse = resultField?.status === "error" || resultField?.operation === "error";
651
+ if (isErrorResponse) {
652
+ return {
653
+ content: subResult.content,
654
+ structuredContent: {
655
+ result: {
656
+ status: "error",
657
+ data: subResult.structuredContent,
658
+ errors: [subResult.content[0]?.text ?? "Sub-tool returned an error"],
659
+ },
660
+ schema: null,
661
+ },
662
+ };
663
+ }
664
+ return {
665
+ content: subResult.content,
666
+ structuredContent: {
667
+ result: {
668
+ status: "success",
669
+ data: subResult.structuredContent,
670
+ },
671
+ schema: null,
672
+ },
673
+ };
674
+ }
675
+ catch (error) {
676
+ const errorMessage = error instanceof Error ? error.message : String(error);
677
+ if (isSchemaValidationError(errorMessage)) {
678
+ const fullSchema = loadPreGeneratedSchema(normalizedToolName) ?? zodToJsonSchemaSafe(entry.config.inputSchema, normalizedToolName);
679
+ const relevantSchema = extractRelevantSchema(fullSchema, normalizedToolName, normalizedData);
680
+ return {
681
+ content: [{
682
+ type: "text",
683
+ text: `Schema mismatch for ${normalizedToolName}: ${errorMessage}`,
684
+ }],
685
+ structuredContent: {
686
+ result: {
687
+ status: "schema_mismatch",
688
+ errors: [errorMessage],
689
+ hint: `Fix your parameters based on the schema below and retry. CACHE THIS SCHEMA for future ${normalizedToolName} calls.`,
690
+ },
691
+ schema: {
692
+ input: relevantSchema,
693
+ tool: normalizedToolName,
694
+ },
695
+ },
696
+ };
697
+ }
698
+ return {
699
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
700
+ structuredContent: {
701
+ result: {
702
+ status: "error",
703
+ errors: [errorMessage],
704
+ },
705
+ schema: null,
706
+ },
707
+ };
708
+ }
709
+ }
390
710
  function zodToJsonSchemaSafe(schema, name) {
391
711
  try {
392
712
  const jsonSchema = zodToJsonSchema(schema, {
@@ -498,49 +818,38 @@ function loadPreGeneratedOutputSchema(toolName) {
498
818
  return null;
499
819
  }
500
820
  export function listTools() {
501
- return TOOL_REGISTRY.map(entry => {
502
- const preGenerated = loadPreGeneratedSchema(entry.name);
503
- const inputSchema = preGenerated ?? zodToJsonSchemaSafe(entry.config.inputSchema, entry.name);
504
- return {
505
- name: entry.name,
506
- title: entry.config.title,
507
- description: entry.config.description,
508
- inputSchema,
509
- };
510
- });
821
+ return [{
822
+ name: "wowok",
823
+ title: "WoWok MCP",
824
+ description: WOWOK_TOOL_DESCRIPTION,
825
+ inputSchema: zodToJsonSchemaSafe(WowokToolDisplaySchema, "wowok"),
826
+ }];
511
827
  }
512
828
  export function registerAllTools(server) {
513
- for (const entry of TOOL_REGISTRY) {
514
- const timeoutMs = entry.timeoutMs ?? 60000;
515
- const handlerWithRules = async (args) => {
516
- return dispatchToolCall(entry.name, args);
517
- };
518
- const wrapped = wrapHandlerWithErrorShape(handlerWithRules, timeoutMs, entry.name, entry.errorShapeBuilder);
519
- server.registerTool(entry.name, entry.config, withTelemetry(entry.name, wrapped));
520
- }
829
+ const timeoutMs = 120000;
830
+ const wrapped = wrapHandlerWithErrorShape(handleWowok, timeoutMs, "wowok", undefined);
831
+ server.registerTool("wowok", {
832
+ title: "WoWok MCP",
833
+ description: WOWOK_TOOL_DESCRIPTION,
834
+ inputSchema: WowokToolRuntimeSchema,
835
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
836
+ }, withTelemetry("wowok", wrapped));
521
837
  overrideToolsListHandler(server);
522
838
  }
523
839
  function overrideToolsListHandler(server) {
524
840
  server.server.setRequestHandler(ListToolsRequestSchema, () => ({
525
- tools: TOOL_REGISTRY.map(entry => {
526
- const rawSchema = loadPreGeneratedSchema(entry.name) ??
527
- zodToJsonSchemaSafe(entry.config.inputSchema, entry.name);
528
- const inputSchema = ensureObjectType(rawSchema);
529
- const toolDef = {
530
- name: entry.name,
531
- title: entry.config.title,
532
- description: entry.config.description,
533
- inputSchema,
534
- annotations: entry.config.annotations,
535
- _meta: entry.config._meta,
536
- };
537
- if (entry.config.outputSchema) {
538
- const outputSchema = loadPreGeneratedOutputSchema(entry.name) ??
539
- zodToJsonSchemaSafe(entry.config.outputSchema, `${entry.name}_output`);
540
- toolDef.outputSchema = outputSchema;
541
- }
542
- return toolDef;
543
- }),
841
+ tools: [{
842
+ name: "wowok",
843
+ title: "WoWok MCP",
844
+ description: WOWOK_TOOL_DESCRIPTION,
845
+ inputSchema: ensureObjectType(zodToJsonSchemaSafe(WowokToolDisplaySchema, "wowok")),
846
+ annotations: {
847
+ readOnlyHint: false,
848
+ destructiveHint: true,
849
+ idempotentHint: false,
850
+ openWorldHint: true,
851
+ },
852
+ }],
544
853
  }));
545
854
  }
546
855
  function ensureObjectType(schema) {
@@ -4,6 +4,7 @@ import { shouldRunLightHooks, shouldRunHeavyHooks, recordOperationFailure, } fro
4
4
  import { getHarness } from "../harness/index.js";
5
5
  import { recordOperationOutcome } from "../experience/index.js";
6
6
  import { recordIndustrySignal } from "../knowledge/flywheel-loop.js";
7
+ import { getStageCache } from "../project/index.js";
7
8
  export function withTimeout(promise, timeoutMs = 30000, operationName = "operation") {
8
9
  let timer;
9
10
  return Promise.race([
@@ -57,6 +58,34 @@ export const operationErrorShape = (error, classified, ctx) => ({
57
58
  export const strictStatusErrorShape = (error, _classified, _ctx) => ({
58
59
  result: { status: "error", error },
59
60
  });
61
+ function checkProjectStage(action, project, version) {
62
+ const entry = getStageCache(project, version);
63
+ if (!entry) {
64
+ if (action === "analyze_intent" || action === "get_project_status") {
65
+ return null;
66
+ }
67
+ return `project_stage: calling '${action}' before 'analyze_intent' — recommend calling analyze_intent first for project '${project}:${version}'`;
68
+ }
69
+ const stageOrder = {
70
+ analyze_intent: 2,
71
+ aggregate_risks: 3,
72
+ generate_deployment_doc: 4,
73
+ trace_substeps: 5,
74
+ };
75
+ const requiredStage = stageOrder[action];
76
+ if (!requiredStage)
77
+ return null;
78
+ if (entry.stage < requiredStage - 1) {
79
+ return `project_stage: calling '${action}' (stage ${requiredStage}) but project is at stage ${entry.stage} — recommend completing prior stages first for '${project}:${version}'`;
80
+ }
81
+ if (action === "generate_deployment_doc" && entry.risk_can_proceed === false) {
82
+ return `project_stage: calling 'generate_deployment_doc' but CRITICAL risks are unresolved — recommend fixing risks first for '${project}:${version}'`;
83
+ }
84
+ if (action === "trace_substeps" && entry.doc_error_count && entry.doc_error_count > 0) {
85
+ return `project_stage: calling 'trace_substeps' but deployment doc has ${entry.doc_error_count} D-error(s) — recommend fixing doc errors first for '${project}:${version}'`;
86
+ }
87
+ return null;
88
+ }
60
89
  export function dispatchWithHarness(handler, toolName) {
61
90
  return async (args) => {
62
91
  const harnessWarnings = [];
@@ -78,6 +107,22 @@ export function dispatchWithHarness(handler, toolName) {
78
107
  harnessWarnings.push(`pre_call hook failed: ${e instanceof Error ? e.message : String(e)}`);
79
108
  }
80
109
  }
110
+ if (toolName === "project_operation" && runLight) {
111
+ try {
112
+ const projArgs = args;
113
+ const action = projArgs?.action;
114
+ const project = projArgs?.project;
115
+ const version = projArgs?.version;
116
+ if (action && project && version) {
117
+ const stageCheck = checkProjectStage(action, project, version);
118
+ if (stageCheck) {
119
+ harnessWarnings.push(stageCheck);
120
+ }
121
+ }
122
+ }
123
+ catch {
124
+ }
125
+ }
81
126
  if (isPublishOp) {
82
127
  try {
83
128
  harnessWarnings.push("pre_publish: full-tier check engaged");
@@ -141,15 +186,24 @@ export function dispatchWithHarness(handler, toolName) {
141
186
  harnessWarnings.push(`signal collection failed: ${e instanceof Error ? e.message : String(e)}`);
142
187
  }
143
188
  }
144
- if (harnessWarnings.length > 0 && result?.structuredContent) {
145
- const sc = result.structuredContent;
146
- const semantic = sc.semantic;
147
- if (semantic) {
148
- const existing = Array.isArray(semantic.harness_warnings) ? semantic.harness_warnings : [];
149
- semantic.harness_warnings = [...existing, ...harnessWarnings];
189
+ if (harnessWarnings.length > 0) {
190
+ if (result?.structuredContent) {
191
+ const sc = result.structuredContent;
192
+ const semantic = sc.semantic;
193
+ if (semantic) {
194
+ const existing = Array.isArray(semantic.warnings) ? semantic.warnings : [];
195
+ semantic.warnings = [...existing, ...harnessWarnings];
196
+ }
197
+ else {
198
+ for (const w of harnessWarnings) {
199
+ console.warn(`[harness] ${w}`);
200
+ }
201
+ }
150
202
  }
151
203
  else {
152
- sc.harness_warnings = harnessWarnings;
204
+ for (const w of harnessWarnings) {
205
+ console.warn(`[harness] ${w}`);
206
+ }
153
207
  }
154
208
  }
155
209
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wowok/agent-mcp",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "description": "Making It Easy for AI Agents to Communicate, Collaborate, Trade, and Trust.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -50,7 +50,7 @@
50
50
  "license": "Apache-2.0",
51
51
  "dependencies": {
52
52
  "@modelcontextprotocol/sdk": "^1.29.0",
53
- "@wowok/wowok": "2.5.0",
53
+ "@wowok/wowok": "2.5.2",
54
54
  "lodash": "^4.18.1",
55
55
  "zod": "^3.25.76",
56
56
  "zod-to-json-schema": "^3.25.2"