@gala-chain/launchpad-mcp-server
Version:
MCP server for Gala Launchpad - 102 tools (pool management, event watchers, GSwap DEX trading, price history, token creation, wallet management, DEX pool discovery, liquidity positions, token locks, locked token queries, composite pool data, cross-chain b
227 lines ⢠7.54 kB
JavaScript
;
/**
* Tool Registry System
*
* Enhanced tool registration with auto-validation, metadata, and search capabilities.
* Provides runtime validation and developer-friendly tool discovery.
*
* @see Phase 3.1 of refactoring plan
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.toolRegistry = void 0;
exports.validateTool = validateTool;
exports.validateTools = validateTools;
exports.createToolRegistry = createToolRegistry;
exports.findTool = findTool;
exports.findToolsByCategory = findToolsByCategory;
exports.searchTools = searchTools;
exports.getToolStatistics = getToolStatistics;
exports.logToolRegistry = logToolRegistry;
exports.generateToolDocumentation = generateToolDocumentation;
// =============================================================================
// Validation Functions
// =============================================================================
/**
* Validates a single tool definition
*/
function validateTool(tool) {
const errors = [];
const warnings = [];
// Required fields
if (!tool.name) {
errors.push('Tool name is required');
}
else if (typeof tool.name !== 'string') {
errors.push('Tool name must be a string');
}
else if (!tool.name.startsWith('gala_launchpad_')) {
warnings.push(`Tool name "${tool.name}" should start with "gala_launchpad_"`);
}
if (!tool.description) {
errors.push('Tool description is required');
}
else if (typeof tool.description !== 'string') {
errors.push('Tool description must be a string');
}
if (!tool.inputSchema) {
errors.push('Tool inputSchema is required');
}
else {
// Validate input schema structure
if (tool.inputSchema.type !== 'object') {
errors.push('inputSchema.type must be "object"');
}
if (!tool.inputSchema.properties) {
warnings.push('inputSchema.properties is empty');
}
if (tool.inputSchema.required && !Array.isArray(tool.inputSchema.required)) {
errors.push('inputSchema.required must be an array');
}
}
if (!tool.handler) {
errors.push('Tool handler is required');
}
else if (typeof tool.handler !== 'function') {
errors.push('Tool handler must be a function');
}
return {
isValid: errors.length === 0,
errors,
warnings,
};
}
/**
* Validates all tools in a registry
*/
function validateTools(tools) {
const allErrors = [];
const allWarnings = [];
const toolNames = new Set();
tools.forEach((tool, index) => {
const result = validateTool(tool);
// Collect errors with tool context
result.errors.forEach((error) => {
allErrors.push(`Tool #${index + 1} (${tool.name || 'unknown'}): ${error}`);
});
result.warnings.forEach((warning) => {
allWarnings.push(`Tool #${index + 1} (${tool.name || 'unknown'}): ${warning}`);
});
// Check for duplicate names
if (tool.name) {
if (toolNames.has(tool.name)) {
allErrors.push(`Duplicate tool name: ${tool.name}`);
}
toolNames.add(tool.name);
}
});
return {
isValid: allErrors.length === 0,
errors: allErrors,
warnings: allWarnings,
};
}
// =============================================================================
// Registry Functions
// =============================================================================
/**
* Creates a tool registry with metadata and validation
*/
function createToolRegistry(categories, expectedCount) {
const allTools = [];
const categoryMap = new Map();
const registryErrors = [];
// Process each category
categories.forEach((category) => {
const toolCategory = {
name: category.name,
description: category.description,
tools: category.tools,
count: category.tools.length,
};
categoryMap.set(category.name, toolCategory);
allTools.push(...category.tools);
});
// Validate all tools
const validation = validateTools(allTools);
registryErrors.push(...validation.errors);
// Check expected count
const actualCount = allTools.length;
const hasExpectedCount = expectedCount !== undefined;
const countMatches = hasExpectedCount ? actualCount === expectedCount : true;
if (hasExpectedCount && !countMatches) {
registryErrors.push(`Tool count mismatch: expected ${expectedCount}, got ${actualCount}`);
}
return {
tools: allTools,
categories: categoryMap,
totalCount: actualCount,
expectedCount: expectedCount ?? actualCount,
isValid: registryErrors.length === 0,
errors: registryErrors,
};
}
/**
* Finds a tool by name
*/
function findTool(registry, name) {
return registry.tools.find((tool) => tool.name === name);
}
/**
* Finds tools by category
*/
function findToolsByCategory(registry, categoryName) {
const category = registry.categories.get(categoryName);
return category ? category.tools : [];
}
/**
* Searches tools by name pattern
*/
function searchTools(registry, pattern) {
const regex = new RegExp(pattern, 'i');
return registry.tools.filter((tool) => regex.test(tool.name));
}
/**
* Gets tool statistics by category
*/
function getToolStatistics(registry) {
const byCategory = {};
registry.categories.forEach((category, name) => {
byCategory[name] = category.count;
});
return {
total: registry.totalCount,
byCategory,
};
}
// =============================================================================
// Logging and Reporting
// =============================================================================
/**
* Logs tool registry statistics
*/
function logToolRegistry(registry) {
console.log('\nš¦ Tool Registry Statistics:');
console.log(` Total Tools: ${registry.totalCount}/${registry.expectedCount}`);
console.log(` Valid: ${registry.isValid ? 'ā
' : 'ā'}`);
if (!registry.isValid && registry.errors.length > 0) {
console.log('\nā Validation Errors:');
registry.errors.forEach((error) => console.log(` - ${error}`));
}
console.log('\nš Categories:');
registry.categories.forEach((category) => {
console.log(` ${category.name}: ${category.count} tools`);
});
console.log('');
}
/**
* Generates markdown documentation for tool registry
*/
function generateToolDocumentation(registry) {
let doc = '# MCP Tool Registry\n\n';
doc += `**Total Tools**: ${registry.totalCount}\n\n`;
doc += '## Categories\n\n';
registry.categories.forEach((category) => {
doc += `### ${category.name} (${category.count} tools)\n\n`;
doc += `${category.description}\n\n`;
category.tools.forEach((tool) => {
doc += `- **${tool.name}**: ${tool.description}\n`;
});
doc += '\n';
});
return doc;
}
// =============================================================================
// Export All
// =============================================================================
exports.toolRegistry = {
createToolRegistry,
validateTool,
validateTools,
findTool,
findToolsByCategory,
searchTools,
getToolStatistics,
logToolRegistry,
generateToolDocumentation,
};
//# sourceMappingURL=tool-registry.js.map