555 lines
24 KiB
JavaScript
555 lines
24 KiB
JavaScript
/**
|
|
* Domain Management MCP Tools
|
|
* Provides CRUD operations for domain registry through MCP interface
|
|
*/
|
|
import { DomainRegistry } from './domain-registry.js';
|
|
export class DomainManagementTools {
|
|
domainRegistry;
|
|
constructor() {
|
|
this.domainRegistry = new DomainRegistry();
|
|
}
|
|
getTools() {
|
|
return [
|
|
{
|
|
name: 'domain_register',
|
|
description: 'Register a new reasoning domain with validation and testing',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: {
|
|
type: 'string',
|
|
pattern: '^[a-z_]+$',
|
|
description: 'Domain identifier (lowercase with underscores)'
|
|
},
|
|
version: {
|
|
type: 'string',
|
|
pattern: '^\\d+\\.\\d+\\.\\d+$',
|
|
description: 'Semantic version (e.g., 1.0.0)'
|
|
},
|
|
description: {
|
|
type: 'string',
|
|
maxLength: 500,
|
|
description: 'Domain description'
|
|
},
|
|
keywords: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 2 },
|
|
minItems: 3,
|
|
uniqueItems: true,
|
|
description: 'Keywords for domain detection (minimum 3 required)'
|
|
},
|
|
reasoning_style: {
|
|
type: 'string',
|
|
enum: [
|
|
'custom', 'mathematical_modeling', 'emergent_systems', 'systematic_analysis',
|
|
'phenomenological', 'temporal_analysis', 'aesthetic_synthesis', 'harmonic_analysis',
|
|
'narrative_analysis', 'conceptual_analysis', 'empathetic_reasoning', 'formal_reasoning',
|
|
'quantitative_analysis', 'creative_synthesis'
|
|
],
|
|
description: 'Reasoning style for this domain'
|
|
},
|
|
custom_reasoning_description: {
|
|
type: 'string',
|
|
description: 'Custom reasoning description (required if reasoning_style is "custom")'
|
|
},
|
|
analogy_domains: {
|
|
type: 'array',
|
|
items: { type: 'string' },
|
|
default: [],
|
|
description: 'Related domains for analogical reasoning'
|
|
},
|
|
semantic_clusters: {
|
|
type: 'array',
|
|
items: { type: 'string' },
|
|
default: [],
|
|
description: 'Semantic concept clusters'
|
|
},
|
|
cross_domain_mappings: {
|
|
type: 'array',
|
|
items: { type: 'string' },
|
|
default: [],
|
|
description: 'Cross-domain connection concepts'
|
|
},
|
|
inference_rules: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string' },
|
|
pattern: { type: 'string' },
|
|
action: { type: 'string' },
|
|
confidence: { type: 'number', minimum: 0, maximum: 1 },
|
|
conditions: { type: 'array', items: { type: 'string' } }
|
|
},
|
|
required: ['name', 'pattern', 'action']
|
|
},
|
|
default: [],
|
|
description: 'Custom inference rules'
|
|
},
|
|
priority: {
|
|
type: 'integer',
|
|
minimum: 0,
|
|
maximum: 100,
|
|
default: 50,
|
|
description: 'Domain priority for detection conflicts (0-100, higher = more priority)'
|
|
},
|
|
dependencies: {
|
|
type: 'array',
|
|
items: { type: 'string' },
|
|
default: [],
|
|
description: 'Required domain dependencies'
|
|
},
|
|
validate_before_register: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Run validation before registration'
|
|
},
|
|
enable_immediately: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Enable domain immediately after registration'
|
|
}
|
|
},
|
|
required: ['name', 'version', 'description', 'keywords', 'reasoning_style']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_list',
|
|
description: 'List all registered domains with status and metadata',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
filter: {
|
|
type: 'string',
|
|
enum: ['all', 'enabled', 'disabled', 'builtin', 'custom'],
|
|
default: 'all',
|
|
description: 'Filter domains by status'
|
|
},
|
|
include_metadata: {
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'Include detailed metadata and performance metrics'
|
|
},
|
|
sort_by: {
|
|
type: 'string',
|
|
enum: ['name', 'priority', 'usage', 'performance'],
|
|
default: 'priority',
|
|
description: 'Sort criteria'
|
|
},
|
|
sort_order: {
|
|
type: 'string',
|
|
enum: ['asc', 'desc'],
|
|
default: 'desc',
|
|
description: 'Sort order'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_get',
|
|
description: 'Get detailed information about a specific domain',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string', description: 'Domain name' },
|
|
include_performance: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Include performance metrics'
|
|
},
|
|
include_usage_stats: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Include usage statistics'
|
|
},
|
|
include_relationships: {
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'Include domain relationships and dependencies'
|
|
}
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_update',
|
|
description: 'Update an existing domain configuration',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string', description: 'Domain name to update' },
|
|
updates: {
|
|
type: 'object',
|
|
description: 'Partial domain configuration updates',
|
|
properties: {
|
|
description: { type: 'string', maxLength: 500 },
|
|
keywords: {
|
|
type: 'array',
|
|
items: { type: 'string', minLength: 2 },
|
|
minItems: 3,
|
|
uniqueItems: true
|
|
},
|
|
reasoning_style: {
|
|
type: 'string',
|
|
enum: [
|
|
'custom', 'mathematical_modeling', 'emergent_systems', 'systematic_analysis',
|
|
'phenomenological', 'temporal_analysis', 'aesthetic_synthesis', 'harmonic_analysis',
|
|
'narrative_analysis', 'conceptual_analysis', 'empathetic_reasoning', 'formal_reasoning',
|
|
'quantitative_analysis', 'creative_synthesis'
|
|
]
|
|
},
|
|
custom_reasoning_description: { type: 'string' },
|
|
analogy_domains: { type: 'array', items: { type: 'string' } },
|
|
semantic_clusters: { type: 'array', items: { type: 'string' } },
|
|
cross_domain_mappings: { type: 'array', items: { type: 'string' } },
|
|
priority: { type: 'integer', minimum: 0, maximum: 100 },
|
|
dependencies: { type: 'array', items: { type: 'string' } }
|
|
}
|
|
},
|
|
validate_before_update: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Run validation before applying updates'
|
|
},
|
|
create_backup: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Create backup before updating'
|
|
}
|
|
},
|
|
required: ['name', 'updates']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_unregister',
|
|
description: 'Unregister a domain from the system',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string', description: 'Domain name to unregister' },
|
|
force: {
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'Force removal even with dependencies (dangerous)'
|
|
},
|
|
cleanup_knowledge: {
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'Remove domain-specific knowledge from knowledge base'
|
|
}
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_enable',
|
|
description: 'Enable a registered domain',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string', description: 'Domain name to enable' }
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_disable',
|
|
description: 'Disable a domain temporarily',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string', description: 'Domain name to disable' }
|
|
},
|
|
required: ['name']
|
|
}
|
|
},
|
|
{
|
|
name: 'domain_system_status',
|
|
description: 'Get overall domain system status and health',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
include_integrity_check: {
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'Run system integrity validation'
|
|
},
|
|
include_performance_summary: {
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'Include performance summary across all domains'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
];
|
|
}
|
|
async handleToolCall(name, args) {
|
|
try {
|
|
switch (name) {
|
|
case 'domain_register':
|
|
return await this.registerDomain(args);
|
|
case 'domain_list':
|
|
return this.listDomains(args);
|
|
case 'domain_get':
|
|
return this.getDomain(args);
|
|
case 'domain_update':
|
|
return await this.updateDomain(args);
|
|
case 'domain_unregister':
|
|
return await this.unregisterDomain(args);
|
|
case 'domain_enable':
|
|
return this.enableDomain(args);
|
|
case 'domain_disable':
|
|
return this.disableDomain(args);
|
|
case 'domain_system_status':
|
|
return this.getSystemStatus(args);
|
|
default:
|
|
throw new Error(`Unknown domain management tool: ${name}`);
|
|
}
|
|
}
|
|
catch (error) {
|
|
return {
|
|
success: false,
|
|
error: error instanceof Error ? error.message : String(error),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
}
|
|
}
|
|
async registerDomain(args) {
|
|
// Validate custom reasoning description if needed
|
|
if (args.reasoning_style === 'custom' && !args.custom_reasoning_description) {
|
|
throw new Error('custom_reasoning_description is required when reasoning_style is "custom"');
|
|
}
|
|
// Build domain configuration
|
|
const config = {
|
|
name: args.name,
|
|
version: args.version,
|
|
description: args.description,
|
|
keywords: args.keywords,
|
|
reasoning_style: args.reasoning_style,
|
|
custom_reasoning_description: args.custom_reasoning_description,
|
|
analogy_domains: args.analogy_domains || [],
|
|
semantic_clusters: args.semantic_clusters || [],
|
|
cross_domain_mappings: args.cross_domain_mappings || [],
|
|
inference_rules: args.inference_rules || [],
|
|
priority: args.priority || 50,
|
|
dependencies: args.dependencies || []
|
|
};
|
|
// Register domain
|
|
const result = await this.domainRegistry.registerDomain(config);
|
|
// Disable if requested
|
|
if (!args.enable_immediately) {
|
|
this.domainRegistry.disableDomain(args.name);
|
|
}
|
|
return {
|
|
success: true,
|
|
domain_id: result.id,
|
|
registered_at: new Date().toISOString(),
|
|
enabled: args.enable_immediately !== false,
|
|
warnings: result.warnings,
|
|
system_status: this.domainRegistry.getSystemStatus()
|
|
};
|
|
}
|
|
listDomains(args) {
|
|
let domains = this.domainRegistry.getAllDomains();
|
|
// Apply filters
|
|
switch (args.filter) {
|
|
case 'enabled':
|
|
domains = domains.filter(d => d.enabled);
|
|
break;
|
|
case 'disabled':
|
|
domains = domains.filter(d => !d.enabled);
|
|
break;
|
|
case 'builtin':
|
|
domains = domains.filter(d => this.domainRegistry.isBuiltinDomain(d.config.name));
|
|
break;
|
|
case 'custom':
|
|
domains = domains.filter(d => !this.domainRegistry.isBuiltinDomain(d.config.name));
|
|
break;
|
|
}
|
|
// Sort domains
|
|
const sortKey = args.sort_by || 'priority';
|
|
const sortOrder = args.sort_order || 'desc';
|
|
domains.sort((a, b) => {
|
|
let comparison = 0;
|
|
switch (sortKey) {
|
|
case 'name':
|
|
comparison = a.config.name.localeCompare(b.config.name);
|
|
break;
|
|
case 'priority':
|
|
comparison = a.config.priority - b.config.priority;
|
|
break;
|
|
case 'usage':
|
|
comparison = a.usage_count - b.usage_count;
|
|
break;
|
|
case 'performance':
|
|
comparison = a.performance_metrics.success_rate - b.performance_metrics.success_rate;
|
|
break;
|
|
}
|
|
return sortOrder === 'desc' ? -comparison : comparison;
|
|
});
|
|
// Format response
|
|
const domainList = domains.map(domain => {
|
|
const basic = {
|
|
name: domain.config.name,
|
|
version: domain.config.version,
|
|
description: domain.config.description,
|
|
enabled: domain.enabled,
|
|
priority: domain.config.priority,
|
|
builtin: this.domainRegistry.isBuiltinDomain(domain.config.name),
|
|
reasoning_style: domain.config.reasoning_style,
|
|
keywords_count: domain.config.keywords.length,
|
|
dependencies_count: domain.config.dependencies.length,
|
|
usage_count: domain.usage_count,
|
|
registered_at: new Date(domain.registered_at).toISOString()
|
|
};
|
|
if (args.include_metadata) {
|
|
return {
|
|
...basic,
|
|
keywords: domain.config.keywords,
|
|
analogy_domains: domain.config.analogy_domains,
|
|
dependencies: domain.config.dependencies,
|
|
performance_metrics: domain.performance_metrics,
|
|
validation_status: domain.validation_status,
|
|
updated_at: new Date(domain.updated_at).toISOString()
|
|
};
|
|
}
|
|
return basic;
|
|
});
|
|
return {
|
|
domains: domainList,
|
|
total: domainList.length,
|
|
filter_applied: args.filter || 'all',
|
|
sort_by: sortKey,
|
|
sort_order: sortOrder,
|
|
system_status: this.domainRegistry.getSystemStatus()
|
|
};
|
|
}
|
|
getDomain(args) {
|
|
const plugin = this.domainRegistry.getDomain(args.name);
|
|
if (!plugin) {
|
|
throw new Error(`Domain '${args.name}' not found`);
|
|
}
|
|
const result = {
|
|
name: plugin.config.name,
|
|
version: plugin.config.version,
|
|
description: plugin.config.description,
|
|
enabled: plugin.enabled,
|
|
builtin: this.domainRegistry.isBuiltinDomain(plugin.config.name),
|
|
config: {
|
|
keywords: plugin.config.keywords,
|
|
reasoning_style: plugin.config.reasoning_style,
|
|
custom_reasoning_description: plugin.config.custom_reasoning_description,
|
|
analogy_domains: plugin.config.analogy_domains,
|
|
semantic_clusters: plugin.config.semantic_clusters,
|
|
cross_domain_mappings: plugin.config.cross_domain_mappings,
|
|
inference_rules: plugin.config.inference_rules,
|
|
priority: plugin.config.priority,
|
|
dependencies: plugin.config.dependencies
|
|
},
|
|
registered_at: new Date(plugin.registered_at).toISOString(),
|
|
updated_at: new Date(plugin.updated_at).toISOString()
|
|
};
|
|
if (args.include_performance) {
|
|
result.performance_metrics = plugin.performance_metrics;
|
|
}
|
|
if (args.include_usage_stats) {
|
|
result.usage_statistics = {
|
|
usage_count: plugin.usage_count,
|
|
last_used: plugin.performance_metrics.last_measured ?
|
|
new Date(plugin.performance_metrics.last_measured).toISOString() : null
|
|
};
|
|
}
|
|
if (args.include_relationships) {
|
|
// Find domains that depend on this one
|
|
const dependents = this.domainRegistry.getAllDomains()
|
|
.filter(d => d.config.dependencies.includes(args.name))
|
|
.map(d => d.config.name);
|
|
// Find domains this one analogizes with
|
|
const analogical_connections = this.domainRegistry.getAllDomains()
|
|
.filter(d => d.config.analogy_domains.includes(args.name) ||
|
|
plugin.config.analogy_domains.includes(d.config.name))
|
|
.map(d => d.config.name);
|
|
result.relationships = {
|
|
dependencies: plugin.config.dependencies,
|
|
dependents,
|
|
analogical_connections: [...new Set(analogical_connections)]
|
|
};
|
|
}
|
|
return result;
|
|
}
|
|
async updateDomain(args) {
|
|
// Validate custom reasoning description if needed
|
|
if (args.updates.reasoning_style === 'custom' && !args.updates.custom_reasoning_description) {
|
|
throw new Error('custom_reasoning_description is required when reasoning_style is "custom"');
|
|
}
|
|
const result = await this.domainRegistry.updateDomain(args.name, args.updates);
|
|
const updatedPlugin = this.domainRegistry.getDomain(args.name);
|
|
return {
|
|
success: true,
|
|
domain_name: args.name,
|
|
updated_at: new Date().toISOString(),
|
|
warnings: result.warnings,
|
|
current_config: updatedPlugin?.config
|
|
};
|
|
}
|
|
async unregisterDomain(args) {
|
|
const result = await this.domainRegistry.unregisterDomain(args.name, {
|
|
force: args.force
|
|
});
|
|
return {
|
|
success: true,
|
|
domain_name: args.name,
|
|
unregistered_at: new Date().toISOString(),
|
|
cleanup_performed: args.cleanup_knowledge,
|
|
system_status: this.domainRegistry.getSystemStatus()
|
|
};
|
|
}
|
|
enableDomain(args) {
|
|
const result = this.domainRegistry.enableDomain(args.name);
|
|
return {
|
|
success: true,
|
|
domain_name: args.name,
|
|
enabled: true,
|
|
enabled_at: new Date().toISOString()
|
|
};
|
|
}
|
|
disableDomain(args) {
|
|
const result = this.domainRegistry.disableDomain(args.name);
|
|
return {
|
|
success: true,
|
|
domain_name: args.name,
|
|
enabled: false,
|
|
disabled_at: new Date().toISOString()
|
|
};
|
|
}
|
|
getSystemStatus(args) {
|
|
const status = this.domainRegistry.getSystemStatus();
|
|
const result = {
|
|
...status,
|
|
timestamp: new Date().toISOString(),
|
|
healthy: true
|
|
};
|
|
if (args.include_integrity_check) {
|
|
const integrity = this.domainRegistry.validateSystemIntegrity();
|
|
result.integrity_check = integrity;
|
|
result.healthy = integrity.valid;
|
|
}
|
|
if (args.include_performance_summary) {
|
|
const domains = this.domainRegistry.getAllDomains();
|
|
const avgSuccessRate = domains.reduce((sum, d) => sum + d.performance_metrics.success_rate, 0) / domains.length;
|
|
const avgResponseTime = domains.reduce((sum, d) => sum + d.performance_metrics.reasoning_time_avg, 0) / domains.length;
|
|
result.performance_summary = {
|
|
average_success_rate: avgSuccessRate,
|
|
average_response_time_ms: avgResponseTime,
|
|
total_usage: domains.reduce((sum, d) => sum + d.usage_count, 0)
|
|
};
|
|
}
|
|
return result;
|
|
}
|
|
// Expose domain registry for other tools
|
|
getDomainRegistry() {
|
|
return this.domainRegistry;
|
|
}
|
|
}
|