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. .
- 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.
- 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.
- Node.js
- npm
-
Clone the repository:
git clone https://github.com/your-repo/mcp-orchestrator.git cd mcp-orchestrator
-
Install Node.js dependencies:
npm install
-
Build the project:
npm run build
-
Run linting:
npm run lint
-
Run tests:
npm run test
To start the orchestrator, run:
npm start
Contributions are welcome! Please open an issue or submit a pull request.
This project is licensed under the MIT License.
"Dev Context" MCP-native orchestrator core:
Key Integrations with MCP:
- Native Message Extensions
- Added orchestration metadata to existing MCP messages
- Maintain backward compatibility with vanilla MCP clients
- Use MCP's existing context propagation mechanisms
- 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
- 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
- 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;
}
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
};
}
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;
}
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);
}
The knowledge graph acts as the semantic backbone of the system, enabling intelligent context management:
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[] { /* ... */ }
}
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
}
}
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
};
}
The metrics collection system provides data-driven insights for continuous optimization:
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
}
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
}
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.