@gala-chain/launchpad-mcp-server 1.22.4 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +83 -8
  3. package/dist/constants/mcpToolNames.d.ts +69 -11
  4. package/dist/constants/mcpToolNames.d.ts.map +1 -1
  5. package/dist/constants/mcpToolNames.js +47 -9
  6. package/dist/constants/mcpToolNames.js.map +1 -1
  7. package/dist/generated/version.d.ts +1 -1
  8. package/dist/generated/version.js +1 -1
  9. package/dist/prompts/balances.d.ts +24 -0
  10. package/dist/prompts/balances.d.ts.map +1 -0
  11. package/dist/prompts/balances.js +191 -0
  12. package/dist/prompts/balances.js.map +1 -0
  13. package/dist/prompts/creation-utils.d.ts +20 -0
  14. package/dist/prompts/creation-utils.d.ts.map +1 -0
  15. package/dist/prompts/creation-utils.js +115 -0
  16. package/dist/prompts/creation-utils.js.map +1 -0
  17. package/dist/prompts/index.d.ts +9 -2
  18. package/dist/prompts/index.d.ts.map +1 -1
  19. package/dist/prompts/index.js +23 -2
  20. package/dist/prompts/index.js.map +1 -1
  21. package/dist/prompts/pools.d.ts +64 -0
  22. package/dist/prompts/pools.d.ts.map +1 -0
  23. package/dist/prompts/pools.js +548 -0
  24. package/dist/prompts/pools.js.map +1 -0
  25. package/dist/prompts/social.d.ts +16 -0
  26. package/dist/prompts/social.d.ts.map +1 -0
  27. package/dist/prompts/social.js +97 -0
  28. package/dist/prompts/social.js.map +1 -0
  29. package/dist/prompts/trading-calculations.d.ts +52 -0
  30. package/dist/prompts/trading-calculations.d.ts.map +1 -0
  31. package/dist/prompts/trading-calculations.js +479 -0
  32. package/dist/prompts/trading-calculations.js.map +1 -0
  33. package/dist/prompts/transfers.d.ts +16 -0
  34. package/dist/prompts/transfers.d.ts.map +1 -0
  35. package/dist/prompts/transfers.js +100 -0
  36. package/dist/prompts/transfers.js.map +1 -0
  37. package/dist/prompts/utility-tools.d.ts +56 -0
  38. package/dist/prompts/utility-tools.d.ts.map +1 -0
  39. package/dist/prompts/utility-tools.js +338 -0
  40. package/dist/prompts/utility-tools.js.map +1 -0
  41. package/docs/AI-AGENT-PATTERNS.md +555 -0
  42. package/docs/CONSTRAINTS-REFERENCE.md +454 -0
  43. package/docs/PROMPT-TOOL-MAPPING.md +352 -0
  44. package/docs/examples/default-values-pattern.md +240 -0
  45. package/docs/examples/tool-factory-pattern.md +217 -0
  46. package/jest.config.js +94 -0
  47. package/package.json +1 -1
  48. package/src/__tests__/integration/fetchTokenDetails.integration.test.ts +258 -0
  49. package/src/__tests__/integration/poolTools.integration.test.ts +185 -0
  50. package/src/__tests__/server.test.ts +256 -0
  51. package/src/constants/mcpToolNames.ts +181 -0
  52. package/src/index.ts +19 -0
  53. package/src/prompts/__tests__/promptStructure.test.ts +137 -0
  54. package/src/prompts/__tests__/registry.test.ts +359 -0
  55. package/src/prompts/analysis.ts +429 -0
  56. package/src/prompts/balances.ts +198 -0
  57. package/src/prompts/create-token.ts +123 -0
  58. package/src/prompts/creation-utils.ts +118 -0
  59. package/src/prompts/dex-trading.ts +86 -0
  60. package/src/prompts/discover-tokens.ts +86 -0
  61. package/src/prompts/index.ts +175 -0
  62. package/src/prompts/liquidity-positions.ts +270 -0
  63. package/src/prompts/pools.ts +571 -0
  64. package/src/prompts/portfolio.ts +242 -0
  65. package/src/prompts/social.ts +100 -0
  66. package/src/prompts/trading-calculations.ts +499 -0
  67. package/src/prompts/trading.ts +191 -0
  68. package/src/prompts/transfers.ts +103 -0
  69. package/src/prompts/utility-tools.ts +349 -0
  70. package/src/prompts/utility.ts +92 -0
  71. package/src/prompts/utils/workflowTemplates.ts +511 -0
  72. package/src/schemas/common-schemas.ts +393 -0
  73. package/src/scripts/test-all-prompts.ts +184 -0
  74. package/src/server.ts +367 -0
  75. package/src/tools/__tests__/dex-tools.test.ts +562 -0
  76. package/src/tools/__tests__/liquidity-positions.test.ts +673 -0
  77. package/src/tools/balance/index.ts +174 -0
  78. package/src/tools/creation/index.ts +182 -0
  79. package/src/tools/dex/index.ts +226 -0
  80. package/src/tools/dex/liquidity-positions.ts +547 -0
  81. package/src/tools/index.ts +94 -0
  82. package/src/tools/pools/fetchAllPools.ts +47 -0
  83. package/src/tools/pools/fetchAllPriceHistory.ts +119 -0
  84. package/src/tools/pools/fetchPoolDetails.ts +27 -0
  85. package/src/tools/pools/fetchPoolDetailsForCalculation.ts +22 -0
  86. package/src/tools/pools/fetchPools.ts +47 -0
  87. package/src/tools/pools/fetchPriceHistory.ts +124 -0
  88. package/src/tools/pools/fetchTokenDetails.ts +77 -0
  89. package/src/tools/pools/index.ts +284 -0
  90. package/src/tools/social/index.ts +64 -0
  91. package/src/tools/trading/index.ts +605 -0
  92. package/src/tools/transfers/index.ts +75 -0
  93. package/src/tools/utils/clearCache.ts +36 -0
  94. package/src/tools/utils/createWallet.ts +19 -0
  95. package/src/tools/utils/explainSdkUsage.ts +1446 -0
  96. package/src/tools/utils/getAddress.ts +12 -0
  97. package/src/tools/utils/getCacheInfo.ts +14 -0
  98. package/src/tools/utils/getConfig.ts +21 -0
  99. package/src/tools/utils/getEnvironment.ts +17 -0
  100. package/src/tools/utils/getEthereumAddress.ts +12 -0
  101. package/src/tools/utils/getUrlByTokenName.ts +12 -0
  102. package/src/tools/utils/getVersion.ts +25 -0
  103. package/src/tools/utils/getWallet.ts +25 -0
  104. package/src/tools/utils/hasWallet.ts +15 -0
  105. package/src/tools/utils/index.ts +37 -0
  106. package/src/tools/utils/isTokenGraduated.ts +16 -0
  107. package/src/tools/utils/setWallet.ts +41 -0
  108. package/src/tools/utils/switchEnvironment.ts +28 -0
  109. package/src/types/mcp.ts +72 -0
  110. package/src/utils/__tests__/validation.test.ts +147 -0
  111. package/src/utils/constraints.ts +155 -0
  112. package/src/utils/default-values.ts +208 -0
  113. package/src/utils/error-handler.ts +69 -0
  114. package/src/utils/error-templates.ts +273 -0
  115. package/src/utils/response-formatter.ts +51 -0
  116. package/src/utils/tool-factory.ts +303 -0
  117. package/src/utils/tool-registry.ts +296 -0
  118. package/src/utils/validation.ts +371 -0
  119. package/tests/wallet-management-integration.test.ts +284 -0
  120. package/tsconfig.json +23 -0
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Tool Factory Pattern Utilities
3
+ *
4
+ * DRY utilities for creating MCP tools with common patterns.
5
+ * Eliminates duplication across 47 tool definitions.
6
+ *
7
+ * @see Phase 2.1 of refactoring plan
8
+ */
9
+
10
+ import type { MCPTool } from '../types/mcp.js';
11
+ import type { LaunchpadSDK } from '@gala-chain/launchpad-sdk';
12
+ import { withErrorHandling } from './error-handler.js';
13
+ import { formatSuccess, formatBoolean } from './response-formatter.js';
14
+ import { TOKEN_NAME_SCHEMA } from '../schemas/common-schemas.js';
15
+
16
+ // =============================================================================
17
+ // Type Definitions
18
+ // =============================================================================
19
+
20
+ /**
21
+ * Handler function that takes SDK and args, returns result
22
+ */
23
+ type ToolHandler<T = any> = (sdk: LaunchpadSDK, args: any) => Promise<T>;
24
+
25
+ /**
26
+ * Simple handler that only needs SDK and tokenName
27
+ * Can return the result or null
28
+ */
29
+ type SimpleTokenHandler<T = any> = (sdk: LaunchpadSDK, tokenName: string) => Promise<T | null>;
30
+
31
+ /**
32
+ * Boolean check handler that returns true/false
33
+ */
34
+ type BooleanCheckHandler = (sdk: LaunchpadSDK, value: string) => Promise<boolean>;
35
+
36
+ /**
37
+ * No-parameter handler that only needs SDK, returns result
38
+ */
39
+ type NoParamHandler<T = any> = (sdk: LaunchpadSDK) => T | Promise<T>;
40
+
41
+ /**
42
+ * Server-level handler that needs server instance for operations like environment switching
43
+ */
44
+ type ServerLevelHandler<T = any> = (sdk: LaunchpadSDK, args: any, server: any) => Promise<T>;
45
+
46
+ // =============================================================================
47
+ // Factory Functions
48
+ // =============================================================================
49
+
50
+ /**
51
+ * Creates a simple fetch tool that takes tokenName and calls an SDK method
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * export const fetchPoolDetailsTool = createSimpleTokenFetchTool({
56
+ * name: 'gala_launchpad_fetch_pool_details',
57
+ * description: 'Get detailed pool state from GalaChain bonding curve',
58
+ * handler: (sdk, tokenName) => sdk.fetchPoolDetails(tokenName),
59
+ * });
60
+ * ```
61
+ */
62
+ export function createSimpleTokenFetchTool(config: {
63
+ name: string;
64
+ description: string;
65
+ handler: SimpleTokenHandler;
66
+ }): MCPTool {
67
+ return {
68
+ name: config.name,
69
+ description: config.description,
70
+ inputSchema: {
71
+ type: 'object',
72
+ properties: {
73
+ tokenName: TOKEN_NAME_SCHEMA,
74
+ },
75
+ required: ['tokenName'],
76
+ },
77
+ handler: withErrorHandling(async (sdk, args) => {
78
+ const result = await config.handler(sdk, args.tokenName);
79
+ return formatSuccess(result);
80
+ }),
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Creates a boolean check tool (e.g., isTokenNameAvailable, isTokenSymbolAvailable)
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * export const checkTokenNameTool = createBooleanCheckTool({
90
+ * name: 'gala_launchpad_check_token_name',
91
+ * description: 'Check if token name is available',
92
+ * paramName: 'tokenName',
93
+ * paramSchema: TOKEN_NAME_SCHEMA,
94
+ * handler: (sdk, tokenName) => sdk.isTokenNameAvailable(tokenName),
95
+ * messages: {
96
+ * true: 'Token name is available',
97
+ * false: 'Token name is already taken',
98
+ * },
99
+ * });
100
+ * ```
101
+ */
102
+ export function createBooleanCheckTool(config: {
103
+ name: string;
104
+ description: string;
105
+ paramName: string;
106
+ paramSchema: any;
107
+ handler: BooleanCheckHandler;
108
+ messages: {
109
+ true: string;
110
+ false: string;
111
+ };
112
+ }): MCPTool {
113
+ return {
114
+ name: config.name,
115
+ description: config.description,
116
+ inputSchema: {
117
+ type: 'object',
118
+ properties: {
119
+ [config.paramName]: config.paramSchema,
120
+ },
121
+ required: [config.paramName],
122
+ },
123
+ handler: withErrorHandling(async (sdk, args) => {
124
+ const value = args[config.paramName];
125
+ const available = await config.handler(sdk, value);
126
+ return formatBoolean(
127
+ available,
128
+ available ? config.messages.true : config.messages.false
129
+ );
130
+ }),
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Creates a generic fetch tool with custom input schema and handler
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * export const fetchPoolsTool = createFetchTool({
140
+ * name: 'gala_launchpad_fetch_pools',
141
+ * description: 'Fetch token pools from Gala Launchpad',
142
+ * inputSchema: {
143
+ * type: 'object',
144
+ * properties: {
145
+ * type: { type: 'string', enum: ['recent', 'popular'] },
146
+ * page: PAGE_SCHEMA,
147
+ * limit: createLimitSchema('pool', 20),
148
+ * },
149
+ * },
150
+ * handler: (sdk, args) => sdk.fetchPools({
151
+ * type: args.type || 'recent',
152
+ * page: args.page || 1,
153
+ * limit: args.limit || 20,
154
+ * }),
155
+ * });
156
+ * ```
157
+ */
158
+ export function createFetchTool(config: {
159
+ name: string;
160
+ description: string;
161
+ inputSchema: {
162
+ type: 'object';
163
+ properties: Record<string, any>;
164
+ required?: string[];
165
+ };
166
+ handler: ToolHandler;
167
+ }): MCPTool {
168
+ return {
169
+ name: config.name,
170
+ description: config.description,
171
+ inputSchema: config.inputSchema,
172
+ handler: withErrorHandling(async (sdk, args) => {
173
+ const result = await config.handler(sdk, args);
174
+ return formatSuccess(result);
175
+ }),
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Creates a resolution tool that maps tokenName to some resolved value
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * export const resolveVaultAddressTool = createResolutionTool({
185
+ * name: 'gala_launchpad_resolve_vault_address',
186
+ * description: 'Get GalaChain vault address for a token',
187
+ * resolver: (sdk, tokenName) => sdk.resolveVaultAddress(tokenName),
188
+ * resultKey: 'vaultAddress',
189
+ * });
190
+ * ```
191
+ */
192
+ export function createResolutionTool(config: {
193
+ name: string;
194
+ description: string;
195
+ resolver: SimpleTokenHandler<string | any>;
196
+ resultKey: string;
197
+ }): MCPTool {
198
+ return {
199
+ name: config.name,
200
+ description: config.description,
201
+ inputSchema: {
202
+ type: 'object',
203
+ properties: {
204
+ tokenName: TOKEN_NAME_SCHEMA,
205
+ },
206
+ required: ['tokenName'],
207
+ },
208
+ handler: withErrorHandling(async (sdk, args) => {
209
+ const resolvedValue = await config.resolver(sdk, args.tokenName);
210
+ return formatSuccess({
211
+ tokenName: args.tokenName,
212
+ [config.resultKey]: resolvedValue,
213
+ });
214
+ }),
215
+ };
216
+ }
217
+
218
+ /**
219
+ * Creates a no-parameter tool that only needs SDK instance
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * export const getAddressTool = createNoParamTool({
224
+ * name: 'gala_launchpad_get_address',
225
+ * description: 'Get the GalaChain address format (eth|0x...) for the authenticated wallet.',
226
+ * handler: (sdk) => sdk.getAddress(),
227
+ * resultKey: 'address',
228
+ * });
229
+ * ```
230
+ */
231
+ export function createNoParamTool(config: {
232
+ name: string;
233
+ description: string;
234
+ handler: NoParamHandler;
235
+ resultKey?: string;
236
+ }): MCPTool {
237
+ return {
238
+ name: config.name,
239
+ description: config.description,
240
+ inputSchema: {
241
+ type: 'object',
242
+ properties: {},
243
+ },
244
+ handler: withErrorHandling(async (sdk) => {
245
+ const result = await config.handler(sdk);
246
+ // If resultKey provided, wrap in object; otherwise return result directly
247
+ return formatSuccess(config.resultKey ? { [config.resultKey]: result } : result);
248
+ }),
249
+ };
250
+ }
251
+
252
+ /**
253
+ * Creates a server-level tool that needs access to the MCP server instance
254
+ * Used for operations like environment switching that require server state management
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * export const getEnvironmentTool = createServerLevelTool({
259
+ * name: 'gala_launchpad_get_environment',
260
+ * description: 'Get the current environment (production, development, or testing).',
261
+ * handler: (sdk, args, server) => server.getEnvironment(),
262
+ * resultKey: 'environment',
263
+ * });
264
+ * ```
265
+ */
266
+ export function createServerLevelTool(config: {
267
+ name: string;
268
+ description: string;
269
+ handler: ServerLevelHandler;
270
+ inputSchema?: {
271
+ type: 'object';
272
+ properties: Record<string, any>;
273
+ required?: string[];
274
+ };
275
+ resultKey?: string;
276
+ }): MCPTool {
277
+ return {
278
+ name: config.name,
279
+ description: config.description,
280
+ inputSchema: config.inputSchema || {
281
+ type: 'object',
282
+ properties: {},
283
+ },
284
+ handler: withErrorHandling(async (sdk, args, server) => {
285
+ const result = await config.handler(sdk, args, server);
286
+ // If resultKey provided, wrap in object; otherwise return result directly
287
+ return formatSuccess(config.resultKey ? { [config.resultKey]: result } : result);
288
+ }),
289
+ };
290
+ }
291
+
292
+ // =============================================================================
293
+ // Exports
294
+ // =============================================================================
295
+
296
+ export const toolFactory = {
297
+ createSimpleTokenFetchTool,
298
+ createBooleanCheckTool,
299
+ createFetchTool,
300
+ createResolutionTool,
301
+ createNoParamTool,
302
+ createServerLevelTool,
303
+ };
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Tool Registry System
3
+ *
4
+ * Enhanced tool registration with auto-validation, metadata, and search capabilities.
5
+ * Provides runtime validation and developer-friendly tool discovery.
6
+ *
7
+ * @see Phase 3.1 of refactoring plan
8
+ */
9
+
10
+ import type { MCPTool } from '../types/mcp.js';
11
+
12
+ // =============================================================================
13
+ // Type Definitions
14
+ // =============================================================================
15
+
16
+ /**
17
+ * Tool category metadata
18
+ */
19
+ export interface ToolCategory {
20
+ name: string;
21
+ description: string;
22
+ tools: MCPTool[];
23
+ count: number;
24
+ }
25
+
26
+ /**
27
+ * Tool registry with metadata and search capabilities
28
+ */
29
+ export interface ToolRegistry {
30
+ tools: MCPTool[];
31
+ categories: Map<string, ToolCategory>;
32
+ totalCount: number;
33
+ expectedCount: number;
34
+ isValid: boolean;
35
+ errors: string[];
36
+ }
37
+
38
+ /**
39
+ * Tool validation result
40
+ */
41
+ export interface ToolValidationResult {
42
+ isValid: boolean;
43
+ errors: string[];
44
+ warnings: string[];
45
+ }
46
+
47
+ // =============================================================================
48
+ // Validation Functions
49
+ // =============================================================================
50
+
51
+ /**
52
+ * Validates a single tool definition
53
+ */
54
+ export function validateTool(tool: MCPTool): ToolValidationResult {
55
+ const errors: string[] = [];
56
+ const warnings: string[] = [];
57
+
58
+ // Required fields
59
+ if (!tool.name) {
60
+ errors.push('Tool name is required');
61
+ } else if (typeof tool.name !== 'string') {
62
+ errors.push('Tool name must be a string');
63
+ } else if (!tool.name.startsWith('gala_launchpad_')) {
64
+ warnings.push(`Tool name "${tool.name}" should start with "gala_launchpad_"`);
65
+ }
66
+
67
+ if (!tool.description) {
68
+ errors.push('Tool description is required');
69
+ } else if (typeof tool.description !== 'string') {
70
+ errors.push('Tool description must be a string');
71
+ }
72
+
73
+ if (!tool.inputSchema) {
74
+ errors.push('Tool inputSchema is required');
75
+ } else {
76
+ // Validate input schema structure
77
+ if (tool.inputSchema.type !== 'object') {
78
+ errors.push('inputSchema.type must be "object"');
79
+ }
80
+ if (!tool.inputSchema.properties) {
81
+ warnings.push('inputSchema.properties is empty');
82
+ }
83
+ if (tool.inputSchema.required && !Array.isArray(tool.inputSchema.required)) {
84
+ errors.push('inputSchema.required must be an array');
85
+ }
86
+ }
87
+
88
+ if (!tool.handler) {
89
+ errors.push('Tool handler is required');
90
+ } else if (typeof tool.handler !== 'function') {
91
+ errors.push('Tool handler must be a function');
92
+ }
93
+
94
+ return {
95
+ isValid: errors.length === 0,
96
+ errors,
97
+ warnings,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Validates all tools in a registry
103
+ */
104
+ export function validateTools(tools: MCPTool[]): ToolValidationResult {
105
+ const allErrors: string[] = [];
106
+ const allWarnings: string[] = [];
107
+ const toolNames = new Set<string>();
108
+
109
+ tools.forEach((tool, index) => {
110
+ const result = validateTool(tool);
111
+
112
+ // Collect errors with tool context
113
+ result.errors.forEach((error) => {
114
+ allErrors.push(`Tool #${index + 1} (${tool.name || 'unknown'}): ${error}`);
115
+ });
116
+
117
+ result.warnings.forEach((warning) => {
118
+ allWarnings.push(`Tool #${index + 1} (${tool.name || 'unknown'}): ${warning}`);
119
+ });
120
+
121
+ // Check for duplicate names
122
+ if (tool.name) {
123
+ if (toolNames.has(tool.name)) {
124
+ allErrors.push(`Duplicate tool name: ${tool.name}`);
125
+ }
126
+ toolNames.add(tool.name);
127
+ }
128
+ });
129
+
130
+ return {
131
+ isValid: allErrors.length === 0,
132
+ errors: allErrors,
133
+ warnings: allWarnings,
134
+ };
135
+ }
136
+
137
+ // =============================================================================
138
+ // Registry Functions
139
+ // =============================================================================
140
+
141
+ /**
142
+ * Creates a tool registry with metadata and validation
143
+ */
144
+ export function createToolRegistry(
145
+ categories: Array<{ name: string; description: string; tools: MCPTool[] }>,
146
+ expectedCount?: number
147
+ ): ToolRegistry {
148
+ const allTools: MCPTool[] = [];
149
+ const categoryMap = new Map<string, ToolCategory>();
150
+ const registryErrors: string[] = [];
151
+
152
+ // Process each category
153
+ categories.forEach((category) => {
154
+ const toolCategory: ToolCategory = {
155
+ name: category.name,
156
+ description: category.description,
157
+ tools: category.tools,
158
+ count: category.tools.length,
159
+ };
160
+
161
+ categoryMap.set(category.name, toolCategory);
162
+ allTools.push(...category.tools);
163
+ });
164
+
165
+ // Validate all tools
166
+ const validation = validateTools(allTools);
167
+ registryErrors.push(...validation.errors);
168
+
169
+ // Check expected count
170
+ const actualCount = allTools.length;
171
+ const hasExpectedCount = expectedCount !== undefined;
172
+ const countMatches = hasExpectedCount ? actualCount === expectedCount : true;
173
+
174
+ if (hasExpectedCount && !countMatches) {
175
+ registryErrors.push(
176
+ `Tool count mismatch: expected ${expectedCount}, got ${actualCount}`
177
+ );
178
+ }
179
+
180
+ return {
181
+ tools: allTools,
182
+ categories: categoryMap,
183
+ totalCount: actualCount,
184
+ expectedCount: expectedCount ?? actualCount,
185
+ isValid: registryErrors.length === 0,
186
+ errors: registryErrors,
187
+ };
188
+ }
189
+
190
+ /**
191
+ * Finds a tool by name
192
+ */
193
+ export function findTool(registry: ToolRegistry, name: string): MCPTool | undefined {
194
+ return registry.tools.find((tool) => tool.name === name);
195
+ }
196
+
197
+ /**
198
+ * Finds tools by category
199
+ */
200
+ export function findToolsByCategory(
201
+ registry: ToolRegistry,
202
+ categoryName: string
203
+ ): MCPTool[] {
204
+ const category = registry.categories.get(categoryName);
205
+ return category ? category.tools : [];
206
+ }
207
+
208
+ /**
209
+ * Searches tools by name pattern
210
+ */
211
+ export function searchTools(registry: ToolRegistry, pattern: string): MCPTool[] {
212
+ const regex = new RegExp(pattern, 'i');
213
+ return registry.tools.filter((tool) => regex.test(tool.name));
214
+ }
215
+
216
+ /**
217
+ * Gets tool statistics by category
218
+ */
219
+ export function getToolStatistics(registry: ToolRegistry): {
220
+ total: number;
221
+ byCategory: Record<string, number>;
222
+ } {
223
+ const byCategory: Record<string, number> = {};
224
+
225
+ registry.categories.forEach((category, name) => {
226
+ byCategory[name] = category.count;
227
+ });
228
+
229
+ return {
230
+ total: registry.totalCount,
231
+ byCategory,
232
+ };
233
+ }
234
+
235
+ // =============================================================================
236
+ // Logging and Reporting
237
+ // =============================================================================
238
+
239
+ /**
240
+ * Logs tool registry statistics
241
+ */
242
+ export function logToolRegistry(registry: ToolRegistry): void {
243
+ console.log('\nšŸ“¦ Tool Registry Statistics:');
244
+ console.log(` Total Tools: ${registry.totalCount}/${registry.expectedCount}`);
245
+ console.log(` Valid: ${registry.isValid ? 'āœ…' : 'āŒ'}`);
246
+
247
+ if (!registry.isValid && registry.errors.length > 0) {
248
+ console.log('\nāŒ Validation Errors:');
249
+ registry.errors.forEach((error) => console.log(` - ${error}`));
250
+ }
251
+
252
+ console.log('\nšŸ“‚ Categories:');
253
+ registry.categories.forEach((category) => {
254
+ console.log(` ${category.name}: ${category.count} tools`);
255
+ });
256
+
257
+ console.log('');
258
+ }
259
+
260
+ /**
261
+ * Generates markdown documentation for tool registry
262
+ */
263
+ export function generateToolDocumentation(registry: ToolRegistry): string {
264
+ let doc = '# MCP Tool Registry\n\n';
265
+ doc += `**Total Tools**: ${registry.totalCount}\n\n`;
266
+
267
+ doc += '## Categories\n\n';
268
+ registry.categories.forEach((category) => {
269
+ doc += `### ${category.name} (${category.count} tools)\n\n`;
270
+ doc += `${category.description}\n\n`;
271
+
272
+ category.tools.forEach((tool) => {
273
+ doc += `- **${tool.name}**: ${tool.description}\n`;
274
+ });
275
+
276
+ doc += '\n';
277
+ });
278
+
279
+ return doc;
280
+ }
281
+
282
+ // =============================================================================
283
+ // Export All
284
+ // =============================================================================
285
+
286
+ export const toolRegistry = {
287
+ createToolRegistry,
288
+ validateTool,
289
+ validateTools,
290
+ findTool,
291
+ findToolsByCategory,
292
+ searchTools,
293
+ getToolStatistics,
294
+ logToolRegistry,
295
+ generateToolDocumentation,
296
+ };