ai-enhanced-tools.ts•15.5 kB
/**
* AI-Enhanced MCP Tools for SAP OData Integration (Fixed Version)
* Tools that leverage AI capabilities for intelligent SAP data operations
*/
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { aiIntegration } from '../services/ai-integration.js';
import { aiQueryBuilder } from '../services/ai-query-builder.js';
import { EntityType } from '../types/sap-types.js';
import { NaturalQueryResult, QueryContext } from '../services/ai-query-builder.js';
import { Logger } from '../utils/logger.js';
const logger = new Logger('AIEnhancedTools');
/**
* Natural Language Query Builder Tool
*/
export class NaturalQueryBuilderTool implements Tool {
[key: string]: unknown;
name = 'natural-query-builder';
description =
'Convert natural language requests into optimized SAP OData queries using AI intelligence. Works with any MCP client (Claude, GPT, etc.)';
inputSchema = {
type: 'object' as const,
properties: {
naturalQuery: {
type: 'string' as const,
description:
'Natural language query (e.g., "Show me all pending invoices from this month with amounts over 1000 euros")',
},
entityType: {
type: 'string' as const,
description: 'Target SAP entity type (e.g., "Invoice", "PurchaseOrder", "Customer")',
},
serviceId: {
type: 'string' as const,
description: 'SAP service identifier',
},
userContext: {
type: 'object' as const,
properties: {
role: { type: 'string' as const },
businessContext: { type: 'string' as const },
preferredFields: {
type: 'array' as const,
items: { type: 'string' as const },
},
},
},
},
required: ['naturalQuery', 'entityType', 'serviceId'],
};
async execute(params: any): Promise<any> {
try {
logger.debug('Processing natural language query', {
query: params.naturalQuery,
entityType: params.entityType,
});
const mockEntityType = this.createMockEntityType(params.entityType);
const result = await aiQueryBuilder.buildQueryFromNaturalLanguage(
params.naturalQuery,
mockEntityType,
params.userContext
);
const executionUrl = `${params.serviceId}/${result.optimizedQuery.url}`;
const suggestions = [
`Try: "${this.generateSuggestion(params.naturalQuery, mockEntityType)}"`,
'Add time filters for better performance',
'Specify fields you need to optimize data transfer',
];
logger.info('Successfully generated natural query', {
originalQuery: params.naturalQuery,
optimizedUrl: result.optimizedQuery.url,
confidence: result.optimizedQuery.confidence,
});
return {
success: true,
result,
executionUrl,
suggestions,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Natural query builder failed', { error: errorMessage });
return {
success: false,
error: errorMessage,
suggestions: [
'Try using simpler language',
'Specify the entity type more clearly',
'Check if the service is available',
],
};
}
}
createMockEntityType(entityTypeName: string): EntityType {
const baseProperties = [
{ name: 'ID', type: 'Edm.String', nullable: false },
{ name: 'CreatedDate', type: 'Edm.DateTime', nullable: true },
{ name: 'Status', type: 'Edm.String', nullable: true },
];
let specificProperties: any[] = [];
if (entityTypeName.toLowerCase().includes('invoice')) {
specificProperties = [
{ name: 'InvoiceNumber', type: 'Edm.String', nullable: false },
{ name: 'Amount', type: 'Edm.Double', nullable: false },
{ name: 'DueDate', type: 'Edm.DateTime', nullable: true },
{ name: 'CustomerName', type: 'Edm.String', nullable: true },
{ name: 'Currency', type: 'Edm.String', nullable: true },
];
} else if (entityTypeName.toLowerCase().includes('customer')) {
specificProperties = [
{ name: 'CustomerNumber', type: 'Edm.String', nullable: false },
{ name: 'Name', type: 'Edm.String', nullable: false },
{ name: 'Email', type: 'Edm.String', nullable: true },
{ name: 'Address', type: 'Edm.String', nullable: true },
{ name: 'Country', type: 'Edm.String', nullable: true },
];
} else {
specificProperties = [
{ name: 'Name', type: 'Edm.String', nullable: true },
{ name: 'Description', type: 'Edm.String', nullable: true },
{ name: 'Value', type: 'Edm.Double', nullable: true },
];
}
return {
name: entityTypeName,
namespace: 'SAP',
entitySet: `${entityTypeName}Set`,
keys: specificProperties.length > 0 ? [specificProperties[0].name] : ['ID'],
properties: [...baseProperties, ...specificProperties],
navigationProperties: [],
// Add missing properties for EntityType compatibility
creatable: true,
updatable: true,
deletable: true,
addressable: true,
};
}
private generateSuggestion(originalQuery: string, entityType: EntityType): string {
const suggestions = [
`Show me recent ${entityType.name.toLowerCase()}s from this week`,
`Find ${entityType.name.toLowerCase()}s with high values`,
`List all pending ${entityType.name.toLowerCase()}s sorted by date`,
`Get ${entityType.name.toLowerCase()}s created today`,
];
return suggestions[Math.floor(Math.random() * suggestions.length)];
}
}
/**
* Smart Data Analysis Tool
*/
export class SmartDataAnalysisTool implements Tool {
[key: string]: unknown;
name = 'smart-data-analysis';
description =
'Analyze SAP data using AI to generate insights, trends, and business recommendations. Compatible with all MCP clients.';
inputSchema = {
type: 'object' as const,
properties: {
data: {
type: 'array' as const,
description: 'Array of data records to analyze - each record is a key-value object',
items: {
type: 'object' as const,
description: 'Data record with flexible schema for SAP entity analysis',
additionalProperties: true,
},
},
analysisType: {
type: 'string' as const,
enum: ['trend', 'anomaly', 'forecast', 'correlation'] as const,
description: 'Type of analysis to perform',
},
businessContext: {
type: 'string' as const,
description: 'Business context for the analysis',
},
entityType: {
type: 'string' as const,
description: 'Type of SAP entity being analyzed',
},
},
required: ['data', 'analysisType', 'entityType'],
};
async execute(params: any): Promise<any> {
try {
logger.info('Starting smart data analysis', {
recordCount: params.data.length,
analysisType: params.analysisType,
entityType: params.entityType,
});
const prompt = `Analyze this ${params.entityType} data for ${params.analysisType} patterns and business insights`;
const analysis = await aiIntegration.analyzeData(prompt, params.data, params.analysisType);
const insights = analysis.insights.map(
(insight: any) => `${insight.title}: ${insight.description} (${insight.impact} impact)`
);
const recommendations = analysis.recommendations.map(
(rec: any) => `${rec.title}: ${rec.description} (Priority: ${rec.priority})`
);
return {
success: true,
analysis,
insights,
recommendations,
confidence: analysis.confidence,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Smart data analysis failed', { error: errorMessage });
return {
success: false,
error: errorMessage,
};
}
}
}
/**
* Query Performance Optimizer Tool
*/
export class QueryPerformanceOptimizerTool implements Tool {
[key: string]: unknown;
name = 'query-performance-optimizer';
description =
'Analyze and optimize SAP OData queries for better performance using AI recommendations.';
inputSchema = {
type: 'object' as const,
properties: {
query: {
type: 'string' as const,
description: 'Original OData query URL to optimize',
},
entityType: {
type: 'string' as const,
description: 'Target entity type',
},
executionStats: {
type: 'object' as const,
properties: {
executionTime: { type: 'number' as const },
recordCount: { type: 'number' as const },
dataSize: { type: 'number' as const },
},
},
optimizationGoals: {
type: 'array' as const,
items: {
type: 'string' as const,
enum: ['speed', 'bandwidth', 'accuracy', 'caching'] as const,
},
description: 'Primary optimization objectives',
},
},
required: ['query', 'entityType'],
};
async execute(params: any): Promise<any> {
try {
logger.info('Optimizing query performance', {
originalQuery: params.query,
entityType: params.entityType,
goals: params.optimizationGoals,
});
// Create mock entity for optimization
const tool = new NaturalQueryBuilderTool();
const mockEntityType = tool.createMockEntityType(params.entityType);
const optimizationResult = await aiIntegration.optimizeQuery(
`Optimize this query for performance: ${params.query}`,
mockEntityType,
{ optimizationGoals: params.optimizationGoals }
);
const improvements = this.analyzeImprovements(params.query, optimizationResult.url);
const performanceGain = this.estimatePerformanceGain(improvements);
return {
success: true,
originalQuery: params.query,
optimizedQuery: optimizationResult.url,
improvements,
performanceGain,
explanation: optimizationResult.explanation,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Query optimization failed', { error: errorMessage });
return {
success: false,
originalQuery: params.query,
error: errorMessage,
};
}
}
private analyzeImprovements(original: string, optimized: string): string[] {
const improvements: string[] = [];
if (optimized.includes('$select') && !original.includes('$select')) {
improvements.push('Added field selection to reduce data transfer');
}
if (optimized.includes('$top') && !original.includes('$top')) {
improvements.push('Added result limit to improve response time');
}
if (improvements.length === 0) {
improvements.push('Query structure optimized for better SAP backend processing');
}
return improvements;
}
private estimatePerformanceGain(improvements: string[]): string {
const totalGain = Math.min(improvements.length * 15, 80);
return `Estimated ${totalGain}% performance improvement`;
}
}
/**
* Business Process Insights Tool
*/
export class BusinessProcessInsightsTool implements Tool {
[key: string]: unknown;
name = 'business-process-insights';
description =
'Analyze SAP business processes to identify bottlenecks, inefficiencies, and optimization opportunities using AI.';
inputSchema = {
type: 'object' as const,
properties: {
processType: {
type: 'string' as const,
enum: ['procurement', 'sales', 'finance', 'inventory', 'hr', 'general'] as const,
description: 'Type of business process to analyze',
},
processData: {
type: 'array' as const,
items: { type: 'object' as const },
description: 'Historical process execution data',
},
timeframe: {
type: 'string' as const,
description: 'Analysis timeframe (e.g., "last 30 days", "Q3 2024")',
},
focusAreas: {
type: 'array' as const,
items: {
type: 'string' as const,
enum: ['efficiency', 'costs', 'compliance', 'quality', 'speed'] as const,
},
description: 'Specific areas to focus the analysis on',
},
},
required: ['processType', 'processData'],
};
async execute(params: any): Promise<any> {
try {
logger.info('Analyzing business process', {
processType: params.processType,
dataPoints: params.processData.length,
timeframe: params.timeframe,
});
const prompt = this.buildProcessAnalysisPrompt(params);
const insights = await aiIntegration.generateBusinessInsights(
params.processData,
`${params.processType}Process`,
prompt
);
const processAnalysis = {
summary: `Analysis of ${params.processType} process over ${params.timeframe || 'specified period'}`,
keyMetrics: this.extractKeyMetrics(params.processData, params.processType),
bottlenecks: insights
.filter((i: any) => i.type === 'risk')
.map((i: any) => i.title)
.slice(0, 5),
optimizationOpportunities: insights
.filter((i: any) => i.type === 'trend')
.map((i: any) => `Optimize ${i.title}`)
.slice(0, 5),
riskAreas: insights
.filter((i: any) => i.type === 'risk')
.map((i: any) => i.description)
.slice(0, 3),
};
const recommendations = insights.map((insight: any) => ({
title: insight.title,
description: insight.description,
priority: insight.impact,
estimatedImpact: `${insight.impact} business impact`,
implementationEffort: 'Medium effort required',
}));
return {
success: true,
processAnalysis,
recommendations,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
logger.error('Business process analysis failed', { error: errorMessage });
return {
success: false,
error: errorMessage,
};
}
}
private buildProcessAnalysisPrompt(params: any): string {
return `Analyze ${params.processType} business process data for insights:
Data points: ${params.processData.length}
Timeframe: ${params.timeframe || 'Not specified'}
Focus areas: ${params.focusAreas?.join(', ') || 'General analysis'}
Identify bottlenecks, inefficiencies, and optimization opportunities.`;
}
private extractKeyMetrics(data: any[], processType: string): Record<string, any> {
return {
totalRecords: data.length,
averageProcessingTime: 0,
completionRate: 0,
};
}
}
// Export all tools
export const aiEnhancedTools = [
new NaturalQueryBuilderTool(),
new SmartDataAnalysisTool(),
new QueryPerformanceOptimizerTool(),
new BusinessProcessInsightsTool(),
];
// Tool registry helpers
export function getAIToolByName(name: string): Tool | undefined {
return aiEnhancedTools.find(tool => tool.name === name);
}
export function getAllAIToolNames(): string[] {
return aiEnhancedTools.map(tool => tool.name);
}
export function getAIToolsCount(): number {
return aiEnhancedTools.length;
}