@gala-chain/launchpad-mcp-server 1.21.6 ā 1.22.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.
- package/CHANGELOG.md +84 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/docs/AI-AGENT-PATTERNS.md +555 -0
- package/docs/CONSTRAINTS-REFERENCE.md +454 -0
- package/docs/PROMPT-TOOL-MAPPING.md +352 -0
- package/docs/examples/default-values-pattern.md +240 -0
- package/docs/examples/tool-factory-pattern.md +217 -0
- package/jest.config.js +94 -0
- package/package.json +2 -2
- package/src/__tests__/integration/fetchTokenDetails.integration.test.ts +258 -0
- package/src/__tests__/integration/poolTools.integration.test.ts +185 -0
- package/src/constants/mcpToolNames.ts +141 -0
- package/src/index.ts +19 -0
- package/src/prompts/__tests__/promptStructure.test.ts +137 -0
- package/src/prompts/__tests__/registry.test.ts +191 -0
- package/src/prompts/analysis.ts +429 -0
- package/src/prompts/create-token.ts +123 -0
- package/src/prompts/dex-trading.ts +86 -0
- package/src/prompts/discover-tokens.ts +86 -0
- package/src/prompts/index.ts +154 -0
- package/src/prompts/liquidity-positions.ts +270 -0
- package/src/prompts/portfolio.ts +242 -0
- package/src/prompts/trading.ts +191 -0
- package/src/prompts/utility.ts +43 -0
- package/src/prompts/utils/workflowTemplates.ts +511 -0
- package/src/schemas/common-schemas.ts +393 -0
- package/src/scripts/test-all-prompts.ts +184 -0
- package/src/server.ts +277 -0
- package/src/tools/__tests__/dex-tools.test.ts +562 -0
- package/src/tools/__tests__/liquidity-positions.test.ts +673 -0
- package/src/tools/balance/index.ts +174 -0
- package/src/tools/creation/index.ts +182 -0
- package/src/tools/dex/index.ts +226 -0
- package/src/tools/dex/liquidity-positions.ts +547 -0
- package/src/tools/index.ts +86 -0
- package/src/tools/pools/fetchAllPools.ts +47 -0
- package/src/tools/pools/fetchAllPriceHistory.ts +119 -0
- package/src/tools/pools/fetchPoolDetails.ts +27 -0
- package/src/tools/pools/fetchPoolDetailsForCalculation.ts +22 -0
- package/src/tools/pools/fetchPools.ts +47 -0
- package/src/tools/pools/fetchPriceHistory.ts +124 -0
- package/src/tools/pools/fetchTokenDetails.ts +77 -0
- package/src/tools/pools/index.ts +284 -0
- package/src/tools/social/index.ts +64 -0
- package/src/tools/trading/index.ts +605 -0
- package/src/tools/transfers/index.ts +75 -0
- package/src/tools/utils/clearCache.ts +36 -0
- package/src/tools/utils/createWallet.ts +19 -0
- package/src/tools/utils/explainSdkUsage.ts +1446 -0
- package/src/tools/utils/getAddress.ts +12 -0
- package/src/tools/utils/getCacheInfo.ts +14 -0
- package/src/tools/utils/getConfig.ts +11 -0
- package/src/tools/utils/getEthereumAddress.ts +12 -0
- package/src/tools/utils/getUrlByTokenName.ts +12 -0
- package/src/tools/utils/getVersion.ts +25 -0
- package/src/tools/utils/getWallet.ts +25 -0
- package/src/tools/utils/hasWallet.ts +15 -0
- package/src/tools/utils/index.ts +33 -0
- package/src/tools/utils/isTokenGraduated.ts +16 -0
- package/src/tools/utils/setWallet.ts +41 -0
- package/src/types/mcp.ts +72 -0
- package/src/utils/__tests__/validation.test.ts +147 -0
- package/src/utils/constraints.ts +155 -0
- package/src/utils/default-values.ts +208 -0
- package/src/utils/error-handler.ts +69 -0
- package/src/utils/error-templates.ts +273 -0
- package/src/utils/response-formatter.ts +51 -0
- package/src/utils/tool-factory.ts +257 -0
- package/src/utils/tool-registry.ts +296 -0
- package/src/utils/validation.ts +371 -0
- package/tests/wallet-management-integration.test.ts +284 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,257 @@
|
|
|
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
|
+
// Factory Functions
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a simple fetch tool that takes tokenName and calls an SDK method
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* export const fetchPoolDetailsTool = createSimpleTokenFetchTool({
|
|
51
|
+
* name: 'gala_launchpad_fetch_pool_details',
|
|
52
|
+
* description: 'Get detailed pool state from GalaChain bonding curve',
|
|
53
|
+
* handler: (sdk, tokenName) => sdk.fetchPoolDetails(tokenName),
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function createSimpleTokenFetchTool(config: {
|
|
58
|
+
name: string;
|
|
59
|
+
description: string;
|
|
60
|
+
handler: SimpleTokenHandler;
|
|
61
|
+
}): MCPTool {
|
|
62
|
+
return {
|
|
63
|
+
name: config.name,
|
|
64
|
+
description: config.description,
|
|
65
|
+
inputSchema: {
|
|
66
|
+
type: 'object',
|
|
67
|
+
properties: {
|
|
68
|
+
tokenName: TOKEN_NAME_SCHEMA,
|
|
69
|
+
},
|
|
70
|
+
required: ['tokenName'],
|
|
71
|
+
},
|
|
72
|
+
handler: withErrorHandling(async (sdk, args) => {
|
|
73
|
+
const result = await config.handler(sdk, args.tokenName);
|
|
74
|
+
return formatSuccess(result);
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Creates a boolean check tool (e.g., isTokenNameAvailable, isTokenSymbolAvailable)
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* export const checkTokenNameTool = createBooleanCheckTool({
|
|
85
|
+
* name: 'gala_launchpad_check_token_name',
|
|
86
|
+
* description: 'Check if token name is available',
|
|
87
|
+
* paramName: 'tokenName',
|
|
88
|
+
* paramSchema: TOKEN_NAME_SCHEMA,
|
|
89
|
+
* handler: (sdk, tokenName) => sdk.isTokenNameAvailable(tokenName),
|
|
90
|
+
* messages: {
|
|
91
|
+
* true: 'Token name is available',
|
|
92
|
+
* false: 'Token name is already taken',
|
|
93
|
+
* },
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function createBooleanCheckTool(config: {
|
|
98
|
+
name: string;
|
|
99
|
+
description: string;
|
|
100
|
+
paramName: string;
|
|
101
|
+
paramSchema: any;
|
|
102
|
+
handler: BooleanCheckHandler;
|
|
103
|
+
messages: {
|
|
104
|
+
true: string;
|
|
105
|
+
false: string;
|
|
106
|
+
};
|
|
107
|
+
}): MCPTool {
|
|
108
|
+
return {
|
|
109
|
+
name: config.name,
|
|
110
|
+
description: config.description,
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: 'object',
|
|
113
|
+
properties: {
|
|
114
|
+
[config.paramName]: config.paramSchema,
|
|
115
|
+
},
|
|
116
|
+
required: [config.paramName],
|
|
117
|
+
},
|
|
118
|
+
handler: withErrorHandling(async (sdk, args) => {
|
|
119
|
+
const value = args[config.paramName];
|
|
120
|
+
const available = await config.handler(sdk, value);
|
|
121
|
+
return formatBoolean(
|
|
122
|
+
available,
|
|
123
|
+
available ? config.messages.true : config.messages.false
|
|
124
|
+
);
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Creates a generic fetch tool with custom input schema and handler
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* export const fetchPoolsTool = createFetchTool({
|
|
135
|
+
* name: 'gala_launchpad_fetch_pools',
|
|
136
|
+
* description: 'Fetch token pools from Gala Launchpad',
|
|
137
|
+
* inputSchema: {
|
|
138
|
+
* type: 'object',
|
|
139
|
+
* properties: {
|
|
140
|
+
* type: { type: 'string', enum: ['recent', 'popular'] },
|
|
141
|
+
* page: PAGE_SCHEMA,
|
|
142
|
+
* limit: createLimitSchema('pool', 20),
|
|
143
|
+
* },
|
|
144
|
+
* },
|
|
145
|
+
* handler: (sdk, args) => sdk.fetchPools({
|
|
146
|
+
* type: args.type || 'recent',
|
|
147
|
+
* page: args.page || 1,
|
|
148
|
+
* limit: args.limit || 20,
|
|
149
|
+
* }),
|
|
150
|
+
* });
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function createFetchTool(config: {
|
|
154
|
+
name: string;
|
|
155
|
+
description: string;
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: 'object';
|
|
158
|
+
properties: Record<string, any>;
|
|
159
|
+
required?: string[];
|
|
160
|
+
};
|
|
161
|
+
handler: ToolHandler;
|
|
162
|
+
}): MCPTool {
|
|
163
|
+
return {
|
|
164
|
+
name: config.name,
|
|
165
|
+
description: config.description,
|
|
166
|
+
inputSchema: config.inputSchema,
|
|
167
|
+
handler: withErrorHandling(async (sdk, args) => {
|
|
168
|
+
const result = await config.handler(sdk, args);
|
|
169
|
+
return formatSuccess(result);
|
|
170
|
+
}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Creates a resolution tool that maps tokenName to some resolved value
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* export const resolveVaultAddressTool = createResolutionTool({
|
|
180
|
+
* name: 'gala_launchpad_resolve_vault_address',
|
|
181
|
+
* description: 'Get GalaChain vault address for a token',
|
|
182
|
+
* resolver: (sdk, tokenName) => sdk.resolveVaultAddress(tokenName),
|
|
183
|
+
* resultKey: 'vaultAddress',
|
|
184
|
+
* });
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export function createResolutionTool(config: {
|
|
188
|
+
name: string;
|
|
189
|
+
description: string;
|
|
190
|
+
resolver: SimpleTokenHandler<string | any>;
|
|
191
|
+
resultKey: string;
|
|
192
|
+
}): MCPTool {
|
|
193
|
+
return {
|
|
194
|
+
name: config.name,
|
|
195
|
+
description: config.description,
|
|
196
|
+
inputSchema: {
|
|
197
|
+
type: 'object',
|
|
198
|
+
properties: {
|
|
199
|
+
tokenName: TOKEN_NAME_SCHEMA,
|
|
200
|
+
},
|
|
201
|
+
required: ['tokenName'],
|
|
202
|
+
},
|
|
203
|
+
handler: withErrorHandling(async (sdk, args) => {
|
|
204
|
+
const resolvedValue = await config.resolver(sdk, args.tokenName);
|
|
205
|
+
return formatSuccess({
|
|
206
|
+
tokenName: args.tokenName,
|
|
207
|
+
[config.resultKey]: resolvedValue,
|
|
208
|
+
});
|
|
209
|
+
}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Creates a no-parameter tool that only needs SDK instance
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* export const getAddressTool = createNoParamTool({
|
|
219
|
+
* name: 'gala_launchpad_get_address',
|
|
220
|
+
* description: 'Get the GalaChain address format (eth|0x...) for the authenticated wallet.',
|
|
221
|
+
* handler: (sdk) => sdk.getAddress(),
|
|
222
|
+
* resultKey: 'address',
|
|
223
|
+
* });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export function createNoParamTool(config: {
|
|
227
|
+
name: string;
|
|
228
|
+
description: string;
|
|
229
|
+
handler: NoParamHandler;
|
|
230
|
+
resultKey?: string;
|
|
231
|
+
}): MCPTool {
|
|
232
|
+
return {
|
|
233
|
+
name: config.name,
|
|
234
|
+
description: config.description,
|
|
235
|
+
inputSchema: {
|
|
236
|
+
type: 'object',
|
|
237
|
+
properties: {},
|
|
238
|
+
},
|
|
239
|
+
handler: withErrorHandling(async (sdk) => {
|
|
240
|
+
const result = await config.handler(sdk);
|
|
241
|
+
// If resultKey provided, wrap in object; otherwise return result directly
|
|
242
|
+
return formatSuccess(config.resultKey ? { [config.resultKey]: result } : result);
|
|
243
|
+
}),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// Exports
|
|
249
|
+
// =============================================================================
|
|
250
|
+
|
|
251
|
+
export const toolFactory = {
|
|
252
|
+
createSimpleTokenFetchTool,
|
|
253
|
+
createBooleanCheckTool,
|
|
254
|
+
createFetchTool,
|
|
255
|
+
createResolutionTool,
|
|
256
|
+
createNoParamTool,
|
|
257
|
+
};
|
|
@@ -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
|
+
};
|