@manifest-network/manifest-mcp-browser 0.1.1 → 0.1.6

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 (131) hide show
  1. package/.github/workflows/publish.yml +4 -2
  2. package/CLAUDE.md +11 -6
  3. package/README.md +1 -1
  4. package/dist/client.d.ts +6 -1
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +77 -21
  7. package/dist/client.js.map +1 -1
  8. package/dist/cosmos.d.ts.map +1 -1
  9. package/dist/cosmos.js +7 -57
  10. package/dist/cosmos.js.map +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +16 -25
  13. package/dist/index.js.map +1 -1
  14. package/dist/modules.d.ts +30 -1
  15. package/dist/modules.d.ts.map +1 -1
  16. package/dist/modules.js +98 -1
  17. package/dist/modules.js.map +1 -1
  18. package/dist/modules.test.js +60 -1
  19. package/dist/modules.test.js.map +1 -1
  20. package/dist/queries/auth.d.ts +7 -1
  21. package/dist/queries/auth.d.ts.map +1 -1
  22. package/dist/queries/auth.js +18 -45
  23. package/dist/queries/auth.js.map +1 -1
  24. package/dist/queries/bank.d.ts +7 -1
  25. package/dist/queries/bank.d.ts.map +1 -1
  26. package/dist/queries/bank.js +24 -38
  27. package/dist/queries/bank.js.map +1 -1
  28. package/dist/queries/billing.d.ts +7 -1
  29. package/dist/queries/billing.d.ts.map +1 -1
  30. package/dist/queries/billing.js +28 -54
  31. package/dist/queries/billing.js.map +1 -1
  32. package/dist/queries/distribution.d.ts +7 -1
  33. package/dist/queries/distribution.d.ts.map +1 -1
  34. package/dist/queries/distribution.js +18 -36
  35. package/dist/queries/distribution.js.map +1 -1
  36. package/dist/queries/gov.d.ts +7 -1
  37. package/dist/queries/gov.d.ts.map +1 -1
  38. package/dist/queries/gov.js +24 -41
  39. package/dist/queries/gov.js.map +1 -1
  40. package/dist/queries/index.d.ts +2 -1
  41. package/dist/queries/index.d.ts.map +1 -1
  42. package/dist/queries/index.js +1 -1
  43. package/dist/queries/index.js.map +1 -1
  44. package/dist/queries/sku.d.ts +13 -0
  45. package/dist/queries/sku.d.ts.map +1 -0
  46. package/dist/queries/sku.js +60 -0
  47. package/dist/queries/sku.js.map +1 -0
  48. package/dist/queries/staking.d.ts +7 -1
  49. package/dist/queries/staking.d.ts.map +1 -1
  50. package/dist/queries/staking.js +36 -59
  51. package/dist/queries/staking.js.map +1 -1
  52. package/dist/queries/utils.d.ts +60 -10
  53. package/dist/queries/utils.d.ts.map +1 -1
  54. package/dist/queries/utils.js +80 -12
  55. package/dist/queries/utils.js.map +1 -1
  56. package/dist/queries/utils.test.js +68 -8
  57. package/dist/queries/utils.test.js.map +1 -1
  58. package/dist/transactions/bank.d.ts +2 -2
  59. package/dist/transactions/bank.d.ts.map +1 -1
  60. package/dist/transactions/bank.js +9 -18
  61. package/dist/transactions/bank.js.map +1 -1
  62. package/dist/transactions/billing.d.ts +2 -2
  63. package/dist/transactions/billing.d.ts.map +1 -1
  64. package/dist/transactions/billing.js +125 -89
  65. package/dist/transactions/billing.js.map +1 -1
  66. package/dist/transactions/distribution.d.ts +2 -2
  67. package/dist/transactions/distribution.d.ts.map +1 -1
  68. package/dist/transactions/distribution.js +7 -13
  69. package/dist/transactions/distribution.js.map +1 -1
  70. package/dist/transactions/gov.d.ts +2 -2
  71. package/dist/transactions/gov.d.ts.map +1 -1
  72. package/dist/transactions/gov.js +29 -20
  73. package/dist/transactions/gov.js.map +1 -1
  74. package/dist/transactions/index.d.ts +1 -1
  75. package/dist/transactions/index.d.ts.map +1 -1
  76. package/dist/transactions/index.js +1 -1
  77. package/dist/transactions/index.js.map +1 -1
  78. package/dist/transactions/manifest.d.ts +2 -2
  79. package/dist/transactions/manifest.d.ts.map +1 -1
  80. package/dist/transactions/manifest.js +7 -14
  81. package/dist/transactions/manifest.js.map +1 -1
  82. package/dist/transactions/sku.d.ts +7 -0
  83. package/dist/transactions/sku.d.ts.map +1 -0
  84. package/dist/transactions/sku.js +184 -0
  85. package/dist/transactions/sku.js.map +1 -0
  86. package/dist/transactions/staking.d.ts +2 -2
  87. package/dist/transactions/staking.d.ts.map +1 -1
  88. package/dist/transactions/staking.js +7 -13
  89. package/dist/transactions/staking.js.map +1 -1
  90. package/dist/transactions/utils.d.ts +65 -1
  91. package/dist/transactions/utils.d.ts.map +1 -1
  92. package/dist/transactions/utils.js +123 -2
  93. package/dist/transactions/utils.js.map +1 -1
  94. package/dist/transactions/utils.test.js +351 -1
  95. package/dist/transactions/utils.test.js.map +1 -1
  96. package/dist/types.d.ts +218 -8
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/types.js.map +1 -1
  99. package/dist/wallet/mnemonic.d.ts +1 -0
  100. package/dist/wallet/mnemonic.d.ts.map +1 -1
  101. package/dist/wallet/mnemonic.js +34 -13
  102. package/dist/wallet/mnemonic.js.map +1 -1
  103. package/package.json +5 -1
  104. package/src/client.ts +84 -21
  105. package/src/cosmos.ts +13 -109
  106. package/src/index.ts +17 -23
  107. package/src/modules.test.ts +62 -0
  108. package/src/modules.ts +155 -5
  109. package/src/queries/auth.ts +35 -74
  110. package/src/queries/bank.ts +40 -58
  111. package/src/queries/billing.ts +46 -86
  112. package/src/queries/distribution.ts +35 -59
  113. package/src/queries/gov.ts +40 -64
  114. package/src/queries/index.ts +10 -1
  115. package/src/queries/sku.ts +85 -0
  116. package/src/queries/staking.ts +55 -91
  117. package/src/queries/utils.test.ts +103 -8
  118. package/src/queries/utils.ts +119 -12
  119. package/src/transactions/bank.ts +9 -33
  120. package/src/transactions/billing.ts +155 -141
  121. package/src/transactions/distribution.ts +7 -29
  122. package/src/transactions/gov.ts +33 -37
  123. package/src/transactions/index.ts +1 -1
  124. package/src/transactions/manifest.ts +7 -29
  125. package/src/transactions/sku.ts +232 -0
  126. package/src/transactions/staking.ts +7 -29
  127. package/src/transactions/utils.test.ts +390 -1
  128. package/src/transactions/utils.ts +194 -2
  129. package/src/types.ts +344 -9
  130. package/src/wallet/mnemonic.ts +41 -17
  131. package/.claude/settings.local.json +0 -20
package/src/cosmos.ts CHANGED
@@ -1,18 +1,6 @@
1
1
  import { CosmosClientManager } from './client.js';
2
2
  import { CosmosQueryResult, CosmosTxResult, ManifestMCPError, ManifestMCPErrorCode } from './types.js';
3
- import { getSupportedModules } from './modules.js';
4
- import { routeBankQuery } from './queries/bank.js';
5
- import { routeStakingQuery } from './queries/staking.js';
6
- import { routeDistributionQuery } from './queries/distribution.js';
7
- import { routeGovQuery } from './queries/gov.js';
8
- import { routeAuthQuery } from './queries/auth.js';
9
- import { routeBillingQuery } from './queries/billing.js';
10
- import { routeBankTransaction } from './transactions/bank.js';
11
- import { routeStakingTransaction } from './transactions/staking.js';
12
- import { routeDistributionTransaction } from './transactions/distribution.js';
13
- import { routeGovTransaction } from './transactions/gov.js';
14
- import { routeBillingTransaction } from './transactions/billing.js';
15
- import { routeManifestTransaction } from './transactions/manifest.js';
3
+ import { getQueryHandler, getTxHandler } from './modules.js';
16
4
 
17
5
  // Validation pattern for module/subcommand names (alphanumeric, hyphens, underscores)
18
6
  // First character must not be a hyphen to prevent potential issues
@@ -30,11 +18,6 @@ function validateName(name: string, field: string): void {
30
18
  }
31
19
  }
32
20
 
33
- // Get module lists from the authoritative registry
34
- const supportedModules = getSupportedModules();
35
- const QUERY_MODULES = Object.keys(supportedModules.query);
36
- const TX_MODULES = Object.keys(supportedModules.tx);
37
-
38
21
  /**
39
22
  * Execute a Cosmos query via manifestjs RPC client
40
23
  */
@@ -52,35 +35,10 @@ export async function cosmosQuery(
52
35
 
53
36
  const queryClient = await clientManager.getQueryClient();
54
37
 
55
- let result: Record<string, unknown>;
56
-
57
38
  try {
58
- switch (module) {
59
- case 'bank':
60
- result = await routeBankQuery(queryClient, subcommand, args);
61
- break;
62
- case 'staking':
63
- result = await routeStakingQuery(queryClient, subcommand, args);
64
- break;
65
- case 'distribution':
66
- result = await routeDistributionQuery(queryClient, subcommand, args);
67
- break;
68
- case 'gov':
69
- result = await routeGovQuery(queryClient, subcommand, args);
70
- break;
71
- case 'auth':
72
- result = await routeAuthQuery(queryClient, subcommand, args);
73
- break;
74
- case 'billing':
75
- result = await routeBillingQuery(queryClient, subcommand, args);
76
- break;
77
- default:
78
- throw new ManifestMCPError(
79
- ManifestMCPErrorCode.UNKNOWN_MODULE,
80
- `Unknown query module: ${module}`,
81
- { availableModules: QUERY_MODULES }
82
- );
83
- }
39
+ // Get handler from registry (throws if module not found)
40
+ const handler = getQueryHandler(module);
41
+ const result = await handler(queryClient, subcommand, args);
84
42
 
85
43
  return {
86
44
  module,
@@ -116,71 +74,17 @@ export async function cosmosTx(
116
74
 
117
75
  const signingClient = await clientManager.getSigningClient();
118
76
  const senderAddress = await clientManager.getAddress();
119
- const config = clientManager.getConfig();
120
77
 
121
78
  try {
122
- switch (module) {
123
- case 'bank':
124
- return await routeBankTransaction(
125
- signingClient,
126
- senderAddress,
127
- subcommand,
128
- args,
129
- config,
130
- waitForConfirmation
131
- );
132
- case 'staking':
133
- return await routeStakingTransaction(
134
- signingClient,
135
- senderAddress,
136
- subcommand,
137
- args,
138
- config,
139
- waitForConfirmation
140
- );
141
- case 'distribution':
142
- return await routeDistributionTransaction(
143
- signingClient,
144
- senderAddress,
145
- subcommand,
146
- args,
147
- config,
148
- waitForConfirmation
149
- );
150
- case 'gov':
151
- return await routeGovTransaction(
152
- signingClient,
153
- senderAddress,
154
- subcommand,
155
- args,
156
- config,
157
- waitForConfirmation
158
- );
159
- case 'billing':
160
- return await routeBillingTransaction(
161
- signingClient,
162
- senderAddress,
163
- subcommand,
164
- args,
165
- config,
166
- waitForConfirmation
167
- );
168
- case 'manifest':
169
- return await routeManifestTransaction(
170
- signingClient,
171
- senderAddress,
172
- subcommand,
173
- args,
174
- config,
175
- waitForConfirmation
176
- );
177
- default:
178
- throw new ManifestMCPError(
179
- ManifestMCPErrorCode.UNKNOWN_MODULE,
180
- `Unknown tx module: ${module}`,
181
- { availableModules: TX_MODULES }
182
- );
183
- }
79
+ // Get handler from registry (throws if module not found)
80
+ const handler = getTxHandler(module);
81
+ return await handler(
82
+ signingClient,
83
+ senderAddress,
84
+ subcommand,
85
+ args,
86
+ waitForConfirmation
87
+ );
184
88
  } catch (error) {
185
89
  if (error instanceof ManifestMCPError) {
186
90
  // Re-throw with enriched context if not already present
package/src/index.ts CHANGED
@@ -32,6 +32,20 @@ const SENSITIVE_FIELDS = new Set([
32
32
  'api_key',
33
33
  ]);
34
34
 
35
+ /**
36
+ * Parse raw args input into string array.
37
+ * Handles both array and space-separated string inputs.
38
+ */
39
+ function parseArgs(rawArgs: unknown): string[] {
40
+ if (Array.isArray(rawArgs)) {
41
+ return rawArgs.map(String);
42
+ }
43
+ if (typeof rawArgs === 'string' && rawArgs.length > 0) {
44
+ return rawArgs.split(/\s+/);
45
+ }
46
+ return [];
47
+ }
48
+
35
49
  /**
36
50
  * Recursively sanitize an object by redacting sensitive fields
37
51
  */
@@ -210,7 +224,7 @@ export class ManifestMCPServer {
210
224
  this.server = new Server(
211
225
  {
212
226
  name: '@manifest-network/manifest-mcp-browser',
213
- version: '0.1.0',
227
+ version: '0.1.1',
214
228
  },
215
229
  {
216
230
  capabilities: {
@@ -297,17 +311,7 @@ export class ManifestMCPServer {
297
311
  case 'cosmos_query': {
298
312
  const module = toolInput.module as string;
299
313
  const subcommand = toolInput.subcommand as string;
300
- const rawArgs = toolInput.args;
301
-
302
- // Handle both array and string inputs for args
303
- let args: string[];
304
- if (Array.isArray(rawArgs)) {
305
- args = rawArgs.map(String);
306
- } else if (typeof rawArgs === 'string' && rawArgs.length > 0) {
307
- args = rawArgs.split(/\s+/);
308
- } else {
309
- args = [];
310
- }
314
+ const args = parseArgs(toolInput.args);
311
315
 
312
316
  if (!module || !subcommand) {
313
317
  throw new ManifestMCPError(
@@ -331,19 +335,9 @@ export class ManifestMCPServer {
331
335
  case 'cosmos_tx': {
332
336
  const module = toolInput.module as string;
333
337
  const subcommand = toolInput.subcommand as string;
334
- const rawArgs = toolInput.args;
338
+ const args = parseArgs(toolInput.args);
335
339
  const waitForConfirmation = (toolInput.wait_for_confirmation as boolean) || false;
336
340
 
337
- // Handle both array and string inputs for args
338
- let args: string[];
339
- if (Array.isArray(rawArgs)) {
340
- args = rawArgs.map(String);
341
- } else if (typeof rawArgs === 'string' && rawArgs.length > 0) {
342
- args = rawArgs.split(/\s+/);
343
- } else {
344
- args = [];
345
- }
346
-
347
341
  if (!module || !subcommand || args.length === 0) {
348
342
  throw new ManifestMCPError(
349
343
  ManifestMCPErrorCode.TX_FAILED,
@@ -4,6 +4,7 @@ import {
4
4
  getModuleSubcommands,
5
5
  isSubcommandSupported,
6
6
  getSupportedModules,
7
+ throwUnsupportedSubcommand,
7
8
  } from './modules.js';
8
9
  import { ManifestMCPError, ManifestMCPErrorCode } from './types.js';
9
10
 
@@ -27,6 +28,7 @@ describe('getAvailableModules', () => {
27
28
  expect(queryNames).toContain('gov');
28
29
  expect(queryNames).toContain('auth');
29
30
  expect(queryNames).toContain('billing');
31
+ expect(queryNames).toContain('sku');
30
32
  });
31
33
 
32
34
  it('should include expected tx modules', () => {
@@ -39,6 +41,7 @@ describe('getAvailableModules', () => {
39
41
  expect(txNames).toContain('gov');
40
42
  expect(txNames).toContain('billing');
41
43
  expect(txNames).toContain('manifest');
44
+ expect(txNames).toContain('sku');
42
45
  });
43
46
  });
44
47
 
@@ -125,3 +128,62 @@ describe('getSupportedModules', () => {
125
128
  expect(modules.tx.bank).toContain('send');
126
129
  });
127
130
  });
131
+
132
+ describe('throwUnsupportedSubcommand', () => {
133
+ it('should throw ManifestMCPError for unsupported query subcommand', () => {
134
+ expect(() => throwUnsupportedSubcommand('query', 'bank', 'unknown')).toThrow(ManifestMCPError);
135
+ });
136
+
137
+ it('should throw ManifestMCPError for unsupported tx subcommand', () => {
138
+ expect(() => throwUnsupportedSubcommand('tx', 'bank', 'unknown')).toThrow(ManifestMCPError);
139
+ });
140
+
141
+ it('should use UNSUPPORTED_QUERY error code for queries', () => {
142
+ try {
143
+ throwUnsupportedSubcommand('query', 'bank', 'unknown');
144
+ } catch (error) {
145
+ expect((error as ManifestMCPError).code).toBe(ManifestMCPErrorCode.UNSUPPORTED_QUERY);
146
+ }
147
+ });
148
+
149
+ it('should use UNSUPPORTED_TX error code for transactions', () => {
150
+ try {
151
+ throwUnsupportedSubcommand('tx', 'bank', 'unknown');
152
+ } catch (error) {
153
+ expect((error as ManifestMCPError).code).toBe(ManifestMCPErrorCode.UNSUPPORTED_TX);
154
+ }
155
+ });
156
+
157
+ it('should include module and subcommand in error message', () => {
158
+ try {
159
+ throwUnsupportedSubcommand('query', 'staking', 'badcmd');
160
+ } catch (error) {
161
+ const message = (error as ManifestMCPError).message;
162
+ expect(message).toContain('staking');
163
+ expect(message).toContain('badcmd');
164
+ expect(message).toContain('query');
165
+ }
166
+ });
167
+
168
+ it('should include availableSubcommands in error details', () => {
169
+ try {
170
+ throwUnsupportedSubcommand('tx', 'bank', 'unknown');
171
+ } catch (error) {
172
+ const details = (error as ManifestMCPError).details;
173
+ expect(details?.availableSubcommands).toBeDefined();
174
+ expect(details?.availableSubcommands).toContain('send');
175
+ expect(details?.availableSubcommands).toContain('multi-send');
176
+ }
177
+ });
178
+
179
+ it('should include correct subcommands for each module', () => {
180
+ try {
181
+ throwUnsupportedSubcommand('query', 'gov', 'unknown');
182
+ } catch (error) {
183
+ const details = (error as ManifestMCPError).details;
184
+ expect(details?.availableSubcommands).toContain('proposal');
185
+ expect(details?.availableSubcommands).toContain('proposals');
186
+ expect(details?.availableSubcommands).toContain('vote');
187
+ }
188
+ });
189
+ });
package/src/modules.ts CHANGED
@@ -1,4 +1,68 @@
1
- import { ModuleInfo, AvailableModules, ManifestMCPError, ManifestMCPErrorCode } from './types.js';
1
+ import { SigningStargateClient } from '@cosmjs/stargate';
2
+ import { ModuleInfo, AvailableModules, ManifestMCPError, ManifestMCPErrorCode, CosmosTxResult, QueryResult } from './types.js';
3
+ import { ManifestQueryClient } from './client.js';
4
+
5
+ // Import query handlers
6
+ import { routeBankQuery } from './queries/bank.js';
7
+ import { routeStakingQuery } from './queries/staking.js';
8
+ import { routeDistributionQuery } from './queries/distribution.js';
9
+ import { routeGovQuery } from './queries/gov.js';
10
+ import { routeAuthQuery } from './queries/auth.js';
11
+ import { routeBillingQuery } from './queries/billing.js';
12
+ import { routeSkuQuery } from './queries/sku.js';
13
+
14
+ // Import transaction handlers
15
+ import { routeBankTransaction } from './transactions/bank.js';
16
+ import { routeStakingTransaction } from './transactions/staking.js';
17
+ import { routeDistributionTransaction } from './transactions/distribution.js';
18
+ import { routeGovTransaction } from './transactions/gov.js';
19
+ import { routeBillingTransaction } from './transactions/billing.js';
20
+ import { routeManifestTransaction } from './transactions/manifest.js';
21
+ import { routeSkuTransaction } from './transactions/sku.js';
22
+
23
+ /**
24
+ * Handler function type for query modules
25
+ */
26
+ export type QueryHandler = (
27
+ queryClient: ManifestQueryClient,
28
+ subcommand: string,
29
+ args: string[]
30
+ ) => Promise<QueryResult>;
31
+
32
+ /**
33
+ * Handler function type for transaction modules
34
+ */
35
+ export type TxHandler = (
36
+ signingClient: SigningStargateClient,
37
+ senderAddress: string,
38
+ subcommand: string,
39
+ args: string[],
40
+ waitForConfirmation: boolean
41
+ ) => Promise<CosmosTxResult>;
42
+
43
+ /**
44
+ * Throw an error for an unsupported subcommand.
45
+ * Automatically looks up available subcommands from the module registry.
46
+ *
47
+ * @param type - 'query' or 'tx'
48
+ * @param module - The module name (e.g., 'bank', 'staking')
49
+ * @param subcommand - The unsupported subcommand that was requested
50
+ */
51
+ export function throwUnsupportedSubcommand(
52
+ type: 'query' | 'tx',
53
+ module: string,
54
+ subcommand: string
55
+ ): never {
56
+ const registry = type === 'query' ? QUERY_MODULES : TX_MODULES;
57
+ const moduleInfo = registry[module];
58
+ const availableSubcommands = moduleInfo?.subcommands.map(s => s.name) ?? [];
59
+
60
+ throw new ManifestMCPError(
61
+ type === 'query' ? ManifestMCPErrorCode.UNSUPPORTED_QUERY : ManifestMCPErrorCode.UNSUPPORTED_TX,
62
+ `Unsupported ${module} ${type === 'query' ? 'query' : 'transaction'} subcommand: ${subcommand}`,
63
+ { availableSubcommands }
64
+ );
65
+ }
2
66
 
3
67
  /**
4
68
  * Static module registry for browser-compatible module discovery
@@ -11,19 +75,30 @@ interface SubcommandInfo {
11
75
  args?: string; // Usage hint for arguments
12
76
  }
13
77
 
14
- interface ModuleRegistry {
78
+ interface QueryModuleRegistry {
79
+ [moduleName: string]: {
80
+ description: string;
81
+ subcommands: SubcommandInfo[];
82
+ handler: QueryHandler;
83
+ };
84
+ }
85
+
86
+ interface TxModuleRegistry {
15
87
  [moduleName: string]: {
16
88
  description: string;
17
89
  subcommands: SubcommandInfo[];
90
+ handler: TxHandler;
18
91
  };
19
92
  }
20
93
 
21
94
  /**
22
95
  * Query modules registry
96
+ * Each module includes metadata and its handler function
23
97
  */
24
- const QUERY_MODULES: ModuleRegistry = {
98
+ const QUERY_MODULES: QueryModuleRegistry = {
25
99
  bank: {
26
100
  description: 'Querying commands for the bank module',
101
+ handler: routeBankQuery,
27
102
  subcommands: [
28
103
  { name: 'balance', description: 'Query account balance for a specific denom' },
29
104
  { name: 'balances', description: 'Query all balances for an account' },
@@ -39,6 +114,7 @@ const QUERY_MODULES: ModuleRegistry = {
39
114
  },
40
115
  staking: {
41
116
  description: 'Querying commands for the staking module',
117
+ handler: routeStakingQuery,
42
118
  subcommands: [
43
119
  { name: 'delegation', description: 'Query a delegation' },
44
120
  { name: 'delegations', description: 'Query all delegations for a delegator' },
@@ -56,6 +132,7 @@ const QUERY_MODULES: ModuleRegistry = {
56
132
  },
57
133
  distribution: {
58
134
  description: 'Querying commands for the distribution module',
135
+ handler: routeDistributionQuery,
59
136
  subcommands: [
60
137
  { name: 'rewards', description: 'Query distribution rewards for a delegator' },
61
138
  { name: 'commission', description: 'Query validator commission' },
@@ -69,6 +146,7 @@ const QUERY_MODULES: ModuleRegistry = {
69
146
  },
70
147
  gov: {
71
148
  description: 'Querying commands for the governance module',
149
+ handler: routeGovQuery,
72
150
  subcommands: [
73
151
  { name: 'proposal', description: 'Query a proposal by ID' },
74
152
  { name: 'proposals', description: 'Query all proposals' },
@@ -82,6 +160,7 @@ const QUERY_MODULES: ModuleRegistry = {
82
160
  },
83
161
  auth: {
84
162
  description: 'Querying commands for the auth module',
163
+ handler: routeAuthQuery,
85
164
  subcommands: [
86
165
  { name: 'account', description: 'Query account by address' },
87
166
  { name: 'accounts', description: 'Query all accounts' },
@@ -96,6 +175,7 @@ const QUERY_MODULES: ModuleRegistry = {
96
175
  },
97
176
  billing: {
98
177
  description: 'Querying commands for the Manifest billing module',
178
+ handler: routeBillingQuery,
99
179
  subcommands: [
100
180
  { name: 'params', description: 'Query billing parameters' },
101
181
  { name: 'lease', description: 'Query a lease by UUID' },
@@ -111,14 +191,29 @@ const QUERY_MODULES: ModuleRegistry = {
111
191
  { name: 'credit-estimate', description: 'Query credit estimate for a tenant' },
112
192
  ],
113
193
  },
194
+ sku: {
195
+ description: 'Querying commands for the Manifest SKU module',
196
+ handler: routeSkuQuery,
197
+ subcommands: [
198
+ { name: 'params', description: 'Query SKU module parameters' },
199
+ { name: 'provider', description: 'Query a provider by UUID', args: '<provider-uuid>' },
200
+ { name: 'providers', description: 'Query all providers', args: '[--active-only] [--limit N]' },
201
+ { name: 'sku', description: 'Query a SKU by UUID', args: '<sku-uuid>' },
202
+ { name: 'skus', description: 'Query all SKUs', args: '[--active-only] [--limit N]' },
203
+ { name: 'skus-by-provider', description: 'Query SKUs by provider UUID', args: '<provider-uuid> [--active-only] [--limit N]' },
204
+ { name: 'provider-by-address', description: 'Query providers by address', args: '<address> [--active-only] [--limit N]' },
205
+ ],
206
+ },
114
207
  };
115
208
 
116
209
  /**
117
210
  * Transaction modules registry
211
+ * Each module includes metadata and its handler function
118
212
  */
119
- const TX_MODULES: ModuleRegistry = {
213
+ const TX_MODULES: TxModuleRegistry = {
120
214
  bank: {
121
215
  description: 'Bank transaction subcommands',
216
+ handler: routeBankTransaction,
122
217
  subcommands: [
123
218
  { name: 'send', description: 'Send tokens to another account', args: '<to-address> <amount> (e.g., manifest1abc... 1000000umfx)' },
124
219
  { name: 'multi-send', description: 'Send tokens to multiple accounts', args: '<to-address:amount>... (e.g., manifest1a:1000umfx manifest1b:2000umfx)' },
@@ -126,6 +221,7 @@ const TX_MODULES: ModuleRegistry = {
126
221
  },
127
222
  staking: {
128
223
  description: 'Staking transaction subcommands',
224
+ handler: routeStakingTransaction,
129
225
  subcommands: [
130
226
  { name: 'delegate', description: 'Delegate tokens to a validator' },
131
227
  { name: 'unbond', description: 'Unbond tokens from a validator' },
@@ -135,6 +231,7 @@ const TX_MODULES: ModuleRegistry = {
135
231
  },
136
232
  distribution: {
137
233
  description: 'Distribution transaction subcommands',
234
+ handler: routeDistributionTransaction,
138
235
  subcommands: [
139
236
  { name: 'withdraw-rewards', description: 'Withdraw rewards from a validator' },
140
237
  { name: 'set-withdraw-addr', description: 'Set withdraw address' },
@@ -143,6 +240,7 @@ const TX_MODULES: ModuleRegistry = {
143
240
  },
144
241
  gov: {
145
242
  description: 'Governance transaction subcommands',
243
+ handler: routeGovTransaction,
146
244
  subcommands: [
147
245
  { name: 'vote', description: 'Vote on a proposal' },
148
246
  { name: 'weighted-vote', description: 'Weighted vote on a proposal' },
@@ -151,20 +249,40 @@ const TX_MODULES: ModuleRegistry = {
151
249
  },
152
250
  billing: {
153
251
  description: 'Manifest billing transaction subcommands',
252
+ handler: routeBillingTransaction,
154
253
  subcommands: [
155
254
  { name: 'fund-credit', description: 'Fund credit for a tenant', args: '<tenant-address> <amount> (e.g., manifest1abc... 1000000umfx)' },
156
255
  { name: 'create-lease', description: 'Create a new lease', args: '[--meta-hash <hex>] <sku-uuid:quantity>... (e.g., sku-123:1 sku-456:2)' },
157
- { name: 'close-lease', description: 'Close one or more leases', args: '<lease-uuid>... (e.g., lease-123 lease-456)' },
256
+ { name: 'close-lease', description: 'Close one or more leases', args: '[--reason <text>] <lease-uuid>... (e.g., lease-123 lease-456)' },
158
257
  { name: 'withdraw', description: 'Withdraw earnings from leases', args: '<lease-uuid>... OR --provider <provider-uuid> [--limit <1-100>]' },
258
+ { name: 'create-lease-for-tenant', description: 'Create a lease on behalf of a tenant', args: '<tenant-address> [--meta-hash <hex>] <sku-uuid:quantity>...' },
259
+ { name: 'acknowledge-lease', description: 'Acknowledge one or more pending leases', args: '<lease-uuid>...' },
260
+ { name: 'reject-lease', description: 'Reject one or more pending leases', args: '[--reason <text>] <lease-uuid>...' },
261
+ { name: 'cancel-lease', description: 'Cancel one or more pending leases', args: '<lease-uuid>...' },
262
+ { name: 'update-params', description: 'Update billing module parameters (governance)', args: '<max-leases-per-tenant> <max-items-per-lease> <min-lease-duration> <max-pending-leases-per-tenant> <pending-timeout> [<allowed-address>...]' },
159
263
  ],
160
264
  },
161
265
  manifest: {
162
266
  description: 'Manifest module transaction subcommands',
267
+ handler: routeManifestTransaction,
163
268
  subcommands: [
164
269
  { name: 'payout', description: 'Execute a payout to multiple addresses' },
165
270
  { name: 'burn-held-balance', description: 'Burn held balance' },
166
271
  ],
167
272
  },
273
+ sku: {
274
+ description: 'Manifest SKU module transaction subcommands',
275
+ handler: routeSkuTransaction,
276
+ subcommands: [
277
+ { name: 'create-provider', description: 'Create a new provider', args: '<address> <payout-address> <api-url> [--meta-hash <hex>]' },
278
+ { name: 'update-provider', description: 'Update an existing provider', args: '<provider-uuid> <address> <payout-address> <api-url> [--meta-hash <hex>] [--active <true|false>]' },
279
+ { name: 'deactivate-provider', description: 'Deactivate a provider', args: '<provider-uuid>' },
280
+ { name: 'create-sku', description: 'Create a new SKU', args: '<provider-uuid> <name> <unit (per-hour|per-day)> <base-price> [--meta-hash <hex>]' },
281
+ { name: 'update-sku', description: 'Update an existing SKU', args: '<sku-uuid> <provider-uuid> <name> <unit (per-hour|per-day)> <base-price> [--meta-hash <hex>] [--active <true|false>]' },
282
+ { name: 'deactivate-sku', description: 'Deactivate a SKU', args: '<sku-uuid>' },
283
+ { name: 'update-params', description: 'Update SKU module parameters (governance)', args: '<allowed-address>...' },
284
+ ],
285
+ },
168
286
  };
169
287
 
170
288
  /**
@@ -276,3 +394,35 @@ export function getSupportedModules(): {
276
394
 
277
395
  return result;
278
396
  }
397
+
398
+ /**
399
+ * Get the handler function for a query module
400
+ * @throws ManifestMCPError if module is not found
401
+ */
402
+ export function getQueryHandler(module: string): QueryHandler {
403
+ const moduleInfo = QUERY_MODULES[module];
404
+ if (!moduleInfo) {
405
+ throw new ManifestMCPError(
406
+ ManifestMCPErrorCode.UNKNOWN_MODULE,
407
+ `Unknown query module: ${module}`,
408
+ { availableModules: Object.keys(QUERY_MODULES) }
409
+ );
410
+ }
411
+ return moduleInfo.handler;
412
+ }
413
+
414
+ /**
415
+ * Get the handler function for a transaction module
416
+ * @throws ManifestMCPError if module is not found
417
+ */
418
+ export function getTxHandler(module: string): TxHandler {
419
+ const moduleInfo = TX_MODULES[module];
420
+ if (!moduleInfo) {
421
+ throw new ManifestMCPError(
422
+ ManifestMCPErrorCode.UNKNOWN_MODULE,
423
+ `Unknown tx module: ${module}`,
424
+ { availableModules: Object.keys(TX_MODULES) }
425
+ );
426
+ }
427
+ return moduleInfo.handler;
428
+ }