Skip to content

Model Context Protocol Orchestrator is being developed as an advanced context compression and task decomposition system for AI development and the structure is designed to be modular, allowing for easy extension and refinement as the system evolves from speculative experimentation..

Notifications You must be signed in to change notification settings

A-Hem/mcp-orchestrator

Repository files navigation

Generate Structure

MCP Orchestrator

Overview (to contribute help organize the code in bottom of this readme into project and new file structure etc, will work on soon just busy ....)

The MCP Orchestrator is the core logic for a modular preprocessor context compression system designed for agent knowledge graph tasks using an extensible architecture. The idea is to leverage it's logic and components to extract max value to and from MCP apis, ai models, and existing knowledge graph, caching, and context preprocessing, compression & optimize task execution, identify and nurture novel ideas. .

Project Structure

Directories structure.md

  • core: Contains the main orchestrator logic.
  • services: Contains various services used by the orchestrator.
  • workers: Contains worker classes for different tasks.
  • data: Contains local data files used by the knowledge graph service.

Files

  • core/orchestrator.ts: Main orchestrator logic.
  • services/cacheService.ts: Cache service for storing and retrieving cached data.
  • services/knowledgeGraphService.ts: Knowledge graph service for managing and querying the knowledge graph.
  • services/contextPreprocessor.ts: Service for preprocessing and compressing context data.
  • workers/localDataWorker.ts: Worker for processing local datasets.
  • workers/staticAnalysisWorker.ts: Worker for performing static code analysis.
  • workers/dependencyCheckerWorker.ts: Worker for checking dependencies.
  • workers/innovationSuggestionWorker.ts: Worker for suggesting innovative features or improvements.
  • data/dbpedia_data.json: Sample DBpedia data file.
  • data/conceptnet_data.json: Sample ConceptNet data file.
  • package.json: Node.js project configuration and dependencies.
  • requirements.txt: Python dependencies (if any).
  • structure.md: Project structure documentation.

Getting Started

Prerequisites

  • Node.js
  • npm

Installation

  1. Clone the repository:

    git clone https://github.com/your-repo/mcp-orchestrator.git
    cd mcp-orchestrator
  2. Install Node.js dependencies:

    npm install
  3. Build the project:

    npm run build
  4. Run linting:

    npm run lint
  5. Run tests:

    npm run test

Usage

To start the orchestrator, run:

npm start

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the MIT License.

"Dev Context" MCP-native orchestrator core:

MCP-Integrated Orchestrator Architecture

Key Integrations with MCP:

  1. Native Message Extensions
  • Added orchestration metadata to existing MCP messages
  • Maintain backward compatibility with vanilla MCP clients
  • Use MCP's existing context propagation mechanisms
  1. Worker Ecosystem
  • Project Scanner uses MCP's file access permissions
  • Command Validator respects MCP's security policies
  • Knowledge Graph builds on MCP's existing context stores
  1. AI Decomposition
  • Uses MCP's existing AI channels with special decomposition markers
  • Maintains MCP's privacy and security constraints
  • Leverages MCP's context caching mechanisms
  1. Feedback Integration #example ```typescript class MCPFeedback extends MCPClient { async submitFeedback( originalMessage: MCPMessage, effectiveness: number ): Promise { await this.sendMessage({ role: 'feedback', content: JSON.stringify({ effectiveness }), metadata: { referenceId: originalMessage.metadata?.messageId, context: originalMessage.metadata?.devContext } }); } }

Implementation Roadmap:

1. **Phase 1: Core Orchestrator**
- Implement MCP message extensions
- Build basic task decomposition
- Create worker API surface

2. **Phase 2: Context-Aware Routing**
- Integrate with DevContext modules
- Add MCP permission checks
- Implement priority queueing

3. **Phase 3: Feedback Integration**
- Add MCP feedback message type
- Connect to knowledge graph
- Implement auto-improvement loops

4. **Phase 4: Advanced Features**
- Cross-session context sharing
- Multi-agent collaboration
- Performance optimization

This approach gives us several advantages:

1. **Incremental Adoption** - Adopt orchestrator features gradually

2. **Context Preservation** - Full MCP context available at every stage

3. **Security Inheritance** - Leverages MCP's existing security model

4. **Protocol Synergy** - Workers benefit from MCP's existing ecosystem
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 Example Workflow Execution
```typescript
// Bootstrap the system
const mcpClient = new MCPClient();
const orchestrator = new MCPOrchestrator(mcpClient);

// Send initial request
mcpClient.sendMessage({
  role: 'user',
  content: 'Why does npm install fail in my project?',
  metadata: {
    sessionId: '123',
    context: {
      currentDir: '/projects/mixed-app',
      os: 'linux'
    }
  }
});

// Worker responses will flow through the orchestrator
mcpClient.onMessage(msg => {
  if (msg.metadata?.taskType === 'project-scan') {
    console.log('Scan result:', msg.content);
  }
  
  if (msg.metadata?.status === 'completed') {
    console.log('Task completed:', msg.metadata.taskId);
  }
});

$$next parts to implement (context compression, algos know graph enhance)

# Advanced Technical Components for MCP Orchestrator

## Context Compression Algorithms

The context compression service employs several sophisticated algorithms working in concert to achieve optimal compression while preserving semantic meaning:

### 1. Semantic Tokenization and Deduplication

The first stage identifies semantically equivalent expressions across contexts. Rather than simple string matching, this approach uses embedding similarity to identify conceptual duplicates that may be expressed differently:

```typescript
function semanticDeduplication(context: ContextSegment[]): ContextSegment[] {
  const embeddingsMap = new Map<string, number[]>();
  const uniqueSegments: ContextSegment[] = [];
  
  // Generate embeddings for all segments
  context.forEach(segment => {
    embeddingsMap.set(segment.id, generateEmbedding(segment.content));
  });
  
  // Identify and merge semantically similar segments
  for (const segment of context) {
    const isUnique = !uniqueSegments.some(existingSegment => {
      const similarity = cosineSimilarity(
        embeddingsMap.get(segment.id)!,
        embeddingsMap.get(existingSegment.id)!
      );
      return similarity > SIMILARITY_THRESHOLD;
    });
    
    if (isUnique) {
      uniqueSegments.push(segment);
    }
  }
  
  return uniqueSegments;
}

2. Contextual Reference Substitution

This technique replaces lengthy repeated information with compact references to a centralized definition:

function referenceSubstitution(segments: ContextSegment[]): CompressedContext {
  const knowledgeNodes = new Map<string, string>();
  const compressedSegments = [];
  
  // First pass: identify potential reference candidates
  segments.forEach(segment => {
    const entities = extractEntities(segment.content);
    entities.forEach(entity => {
      if (entity.description.length > MIN_REFERENCE_LENGTH) {
        knowledgeNodes.set(entity.id, entity.description);
      }
    });
  });
  
  // Second pass: replace with references
  segments.forEach(segment => {
    let compressedContent = segment.content;
    knowledgeNodes.forEach((description, id) => {
      if (compressedContent.includes(description)) {
        compressedContent = compressedContent.replace(
          description, 
          `[REF:${id}]`
        );
      }
    });
    
    compressedSegments.push({
      ...segment,
      content: compressedContent,
    });
  });
  
  return {
    segments: compressedSegments,
    referenceTable: knowledgeNodes,
    // Additional metadata
  };
}

3. Progressive Lossy Compression

For lower-priority contexts, a progressive lossy approach can be employed to retain core meaning while reducing token count:

function progressiveLossyCompression(
  segment: ContextSegment, 
  importanceThreshold: number
): ContextSegment {
  if (segment.metadata.importance < importanceThreshold) {
    // Extract key sentences using extractive summarization
    const sentences = splitIntoSentences(segment.content);
    const rankedSentences = rankSentencesByImportance(sentences);
    
    // Retain only the top N% based on importance score
    const retentionRatio = calculateRetentionRatio(segment.metadata.importance);
    const sentencesToKeep = Math.ceil(sentences.length * retentionRatio);
    
    const compressedContent = rankedSentences
      .slice(0, sentencesToKeep)
      .join(' ');
    
    return {
      ...segment,
      content: compressedContent,
      metadata: {
        ...segment.metadata,
        isLossyCompressed: true,
        compressionRatio: sentencesToKeep / sentences.length,
      }
    };
  }
  
  return segment;
}

4. Adaptive Compression Strategy

The system dynamically selects optimal compression strategies based on context type and usage patterns:

function adaptiveCompression(
  context: ContextSegment[],
  usageStats: ContextUsageStatistics
): CompressedContext {
  // Analyze context to determine optimal compression approach
  const contextType = classifyContextType(context);
  const compressionProfile = compressionProfiles.get(contextType);
  
  // Apply appropriate compression techniques based on profile
  let compressedContext;
  
  switch (compressionProfile.primaryStrategy) {
    case 'semantic':
      compressedContext = semanticDeduplication(context);
      break;
    case 'reference':
      compressedContext = referenceSubstitution(context);
      break;
    case 'lossy':
      compressedContext = context.map(segment => 
        progressiveLossyCompression(segment, compressionProfile.thresholds.importance)
      );
      break;
    case 'hybrid':
      // Apply multiple strategies in sequence
      compressedContext = hybridCompression(context, compressionProfile);
      break;
  }
  
  // Update compression statistics for future optimization
  updateCompressionStats(contextType, {
    originalSize: calculateTokenCount(context),
    compressedSize: calculateTokenCount(compressedContext),
    preservationScore: evaluateSemanticPreservation(context, compressedContext)
  });
  
  return finalizeCompression(compressedContext);
}

Knowledge Graph Integration

The knowledge graph acts as the semantic backbone of the system, enabling intelligent context management:

1. Dynamic Knowledge Graph Structure

interface KnowledgeNode {
  id: string;
  label: string;
  type: 'entity' | 'concept' | 'relation' | 'context';
  properties: Map<string, any>;
  confidence: number;
  lastUpdated: number;
  sources: string[];
}

interface KnowledgeEdge {
  source: string;
  target: string;
  relation: string;
  weight: number;
  properties: Map<string, any>;
}

class KnowledgeGraph {
  private nodes: Map<string, KnowledgeNode>;
  private edges: Map<string, KnowledgeEdge[]>;
  private indexers: Map<string, (node: KnowledgeNode) => any>;
  
  constructor() {
    this.nodes = new Map();
    this.edges = new Map();
    this.indexers = new Map();
    this.setupIndexers();
  }
  
  // Methods for graph management and querying
  public addNode(node: KnowledgeNode): void { /* ... */ }
  public addEdge(edge: KnowledgeEdge): void { /* ... */ }
  public findRelatedNodes(nodeId: string, maxDistance: number = 2): KnowledgeNode[] { /* ... */ }
  public queryByProperty(property: string, value: any): KnowledgeNode[] { /* ... */ }
  
  // Context-specific methods
  public extractContextualKnowledge(context: ContextSegment[]): void { /* ... */ }
  public generateContextForQuery(query: string): ContextSegment[] { /* ... */ }
}

2. Context-Knowledge Integration

class ContextKnowledgeIntegrator {
  private knowledgeGraph: KnowledgeGraph;
  private contextRegistry: ContextRegistry;
  
  constructor(knowledgeGraph: KnowledgeGraph, contextRegistry: ContextRegistry) {
    this.knowledgeGraph = knowledgeGraph;
    this.contextRegistry = contextRegistry;
  }
  
  /**
   * Updates knowledge graph with insights from new context
   */
  public integrateContext(context: ContextSegment[]): void {
    // Extract entities and concepts
    const extractedKnowledge = this.extractKnowledge(context);
    
    // Update knowledge graph
    extractedKnowledge.entities.forEach(entity => {
      this.knowledgeGraph.addOrUpdateNode({
        id: entity.id,
        label: entity.name,
        type: 'entity',
        properties: entity.properties,
        confidence: entity.confidence,
        lastUpdated: Date.now(),
        sources: [context[0].metadata.source]
      });
    });
    
    // Add relationships between context and knowledge
    context.forEach(segment => {
      extractedKnowledge.entityReferences
        .filter(ref => ref.segmentId === segment.id)
        .forEach(ref => {
          this.knowledgeGraph.addEdge({
            source: segment.id,
            target: ref.entityId,
            relation: 'mentions',
            weight: ref.importance,
            properties: new Map([['position', ref.position]])
          });
        });
    });
  }
  
  /**
   * Retrieves relevant knowledge for context enrichment
   */
  public enrichContextWithKnowledge(context: ContextSegment[]): EnrichedContext {
    // Implementation for context enrichment
  }
}

3. Knowledge-Driven Compression

function knowledgeDrivenCompression(
  context: ContextSegment[],
  knowledgeGraph: KnowledgeGraph
): CompressedContext {
  // Identify entities and concepts in context
  const contextEntities = extractEntitiesFromContext(context);
  
  // For each entity, retrieve its canonical representation
  const canonicalRepresentations = new Map<string, string>();
  contextEntities.forEach(entity => {
    const knowledgeNode = knowledgeGraph.getNode(entity.id);
    if (knowledgeNode) {
      canonicalRepresentations.set(
        entity.id, 
        generateCanonicalForm(knowledgeNode)
      );
    }
  });
  
  // Replace entity mentions with canonical forms
  const compressedSegments = context.map(segment => {
    let compressedContent = segment.content;
    contextEntities
      .filter(entity => entity.segmentId === segment.id)
      .forEach(entity => {
        if (canonicalRepresentations.has(entity.id)) {
          compressedContent = replaceEntityMention(
            compressedContent,
            entity.mention,
            canonicalRepresentations.get(entity.id)!
          );
        }
      });
    
    return {
      ...segment,
      content: compressedContent
    };
  });
  
  return {
    segments: compressedSegments,
    knowledgeReferences: Array.from(canonicalRepresentations.keys()),
    // Additional metadata
  };
}

Metrics Collection and Performance Tuning

The metrics collection system provides data-driven insights for continuous optimization:

1. Comprehensive Metrics Framework

class MetricsCollector {
  private metrics: Map<string, MetricSeries>;
  private thresholds: Map<string, number>;
  private alertHandlers: Map<string, (value: number) => void>;
  
  constructor() {
    this.metrics = new Map();
    this.thresholds = new Map();
    this.alertHandlers = new Map();
    this.initializeMetrics();
  }
  
  private initializeMetrics(): void {
    // Initialize core metrics
    this.registerMetric('compression.ratio', 'running_average');
    this.registerMetric('compression.semantic_preservation', 'running_average');
    this.registerMetric('compression.processing_time', 'histogram');
    
    this.registerMetric('knowledgegraph.node_count', 'gauge');
    this.registerMetric('knowledgegraph.edge_count', 'gauge');
    this.registerMetric('knowledgegraph.query_time', 'histogram');
    
    this.registerMetric('context.token_count', 'histogram');
    this.registerMetric('context.processing_time', 'histogram');
    
    this.registerMetric('task.decomposition_count', 'histogram');
    this.registerMetric('task.completion_time', 'histogram');
    
    // Set thresholds and alerts
    this.setThreshold('compression.ratio', 0.4);  // Alert if compression below 40%
    this.setThreshold('compression.semantic_preservation', 0.85);  // Alert if preservation below 85%
    this.setThreshold('knowledgegraph.query_time', 200);  // Alert if queries exceed 200ms
  }
  
  public recordMetric(name: string, value: number): void {
    if (!this.metrics.has(name)) {
      console.warn(`Unregistered metric: ${name}`);
      return;
    }
    
    const metric = this.metrics.get(name)!;
    metric.record(value);
    
    // Check thresholds
    if (this.thresholds.has(name)) {
      const threshold = this.thresholds.get(name)!;
      const isAlert = this.checkThreshold(name, value, threshold);
      
      if (isAlert && this.alertHandlers.has(name)) {
        this.alertHandlers.get(name)!(value);
      }
    }
  }
  
  // Additional methods for metric management
}

2. Performance Optimization Pipeline

class PerformanceOptimizer {
  private metricsCollector: MetricsCollector;
  private configManager: ConfigManager;
  
  constructor(metricsCollector: MetricsCollector, configManager: ConfigManager) {
    this.metricsCollector = metricsCollector;
    this.configManager = configManager;
    this.setupOptimizationPipeline();
  }
  
  private setupOptimizationPipeline(): void {
    // Schedule regular optimization runs
    setInterval(() => this.runOptimizationCycle(), OPTIMIZATION_INTERVAL);
    
    // Set up reactive optimizations based on metrics
    this.metricsCollector.onThresholdCrossed(
      'compression.ratio',
      (value) => this.optimizeCompressionSettings(value)
    );
    
    this.metricsCollector.onThresholdCrossed(
      'task.completion_time',
      (value) => this.optimizeTaskDecomposition(value)
    );
  }
  
  private async runOptimizationCycle(): Promise<void> {
    // Collect current performance metrics
    const performanceSnapshot = this.collectPerformanceMetrics();
    
    // Identify optimization opportunities
    const optimizationTargets = this.identifyOptimizationTargets(performanceSnapshot);
    
    // Apply optimizations
    for (const target of optimizationTargets) {
      await this.applyOptimization(target);
    }
    
    // Record optimization results
    this.recordOptimizationResults();
  }
  
  private optimizeCompressionSettings(currentRatio: number): void {
    // Adjust compression parameters based on current performance
    const currentSettings = this.configManager.getConfig('compression');
    
    if (currentRatio < LOW_COMPRESSION_THRESHOLD) {
      // Increase aggressiveness of compression
      const newSettings = {
        ...currentSettings,
        semanticThreshold: Math.max(currentSettings.semanticThreshold - 0.05, MIN_SEMANTIC_THRESHOLD),
        enableLossyCompression: true,
        lossyCompressionThreshold: currentSettings.lossyCompressionThreshold * 1.2
      };
      
      this.configManager.updateConfig('compression', newSettings);
      this.metricsCollector.recordMetric('optimization.compression_updates', 1);
    }
  }
  
  // Additional optimization methods
}

3. A/B Testing Framework for Algorithms

class AlgorithmTestingFramework {
  private metricsCollector: MetricsCollector;
  private activeExperiments: Map<string, Experiment>;
  
  constructor(metricsCollector: MetricsCollector) {
    this.metricsCollector = metricsCollector;
    this.activeExperiments = new Map();
  }
  
  /**
   * Sets up an A/B test for algorithm variants
   */
  public setupExperiment(
    name: string, 
    variants: AlgorithmVariant[],
    targetMetrics: string[],
    sampleSize: number
  ): Experiment {
    const experiment: Experiment = {
      name,
      variants,
      targetMetrics,
      sampleSize,
      results: new Map(),
      status: 'running',
      startTime: Date.now()
    };
    
    this.activeExperiments.set(name, experiment);
    return experiment;
  }
  
  /**
   * Selects algorithm variant to use based on active experiments
   */
  public selectVariant(algorithmName: string): AlgorithmVariant {
    const relevantExperiments = Array.from(this.activeExperiments.values())
      .filter(exp => exp.variants.some(v => v.algorithmName === algorithmName));
    
    if (relevantExperiments.length === 0) {
      return this.getDefaultVariant(algorithmName);
    }
    
    // Select experiment with highest priority
    const experiment = relevantExperiments.sort((a, b) => b.priority - a.priority)[0];
    
    // Implement selection strategy (random, weighted, etc.)
    return this.selectVariantFromExperiment(experiment);
  }
  
  /**
   * Records result of using a particular variant
   */
  public recordVariantResult(
    experimentName: string,
    variantId: string,
    metrics: Map<string, number>
  ): void {
    const experiment = this.activeExperiments.get(experimentName);
    if (!experiment) return;
    
    // Record metrics for this variant
    if (!experiment.results.has(variantId)) {
      experiment.results.set(variantId, []);
    }
    
    experiment.results.get(variantId)!.push({
      timestamp: Date.now(),
      metrics: new Map(metrics)
    });
    
    // Check if experiment has sufficient data
    this.checkExperimentCompletion(experimentName);
  }
  
  /**
   * Analyzes experiment results and selects winner
   */
  private analyzeExperimentResults(experiment: Experiment): AlgorithmVariant {
    // Statistical analysis of variant performance
    const variantPerformance = new Map<string, Map<string, number>>();
    
    // Calculate average performance for each variant
    experiment.variants.forEach(variant => {
      const results = experiment.results.get(variant.id) || [];
      const metricAverages = new Map<string, number>();
      
      experiment.targetMetrics.forEach(metricName => {
        const values = results
          .map(result => result.metrics.get(metricName) || 0)
          .filter(value => value !== 0);
        
        if (values.length > 0) {
          const average = values.reduce((sum, value) => sum + value, 0) / values.length;
          metricAverages.set(metricName, average);
        }
      });
      
      variantPerformance.set(variant.id, metricAverages);
    });
    
    // Select winner based on performance weights
    return this.selectWinningVariant(experiment, variantPerformance);
  }
  
  // Additional methods for experiment management
}

These detailed implementations showcase the sophisticated approaches used in the MCP Orchestrator to achieve optimal context management, knowledge integration, and continuous performance improvement. The system's strength lies in its ability to adaptively optimize its behavior based on operational data, enabling ever-more-efficient processing of contextual information.

About

Model Context Protocol Orchestrator is being developed as an advanced context compression and task decomposition system for AI development and the structure is designed to be modular, allowing for easy extension and refinement as the system evolves from speculative experimentation..

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published