mcp-context-engineering
Version:
The intelligent context optimization system for AI coding assistants. Built with Cole's PRP methodology, Context Portal knowledge graphs, and production-ready MongoDB architecture.
622 lines (621 loc) β’ 24.4 kB
JavaScript
import { z } from 'zod';
import { ObjectId } from 'mongodb';
import { COLLECTIONS } from '../../mongodb/models/contextPattern.js';
import { getConnectionManager } from '../../mongodb/operations/connection.js';
import { securityManager } from '../../security/securityManager.js';
import { performanceOptimizer } from '../../performance/performanceOptimizer.js';
/**
* Knowledge Graph Manager - Context Portal Integration
*
* Implements Context Portal's sophisticated knowledge graph patterns:
* - Explicit relationship modeling with directional links
* - Hierarchical progress tracking with parent-child relationships
* - Structured decision capture with rationale and consequences
* - System pattern management with usage examples and trade-offs
* - Cross-workspace knowledge sharing with access control
* - Real-time graph traversal and relationship discovery
*/
// Graph query schema
export const GraphQuerySchema = z.object({
workspace_id: z.string(),
query_type: z.enum(['traverse', 'find_related', 'pattern_search', 'decision_path', 'impact_analysis']),
// Source entity
source: z.object({
item_type: z.string(),
item_id: z.string()
}).optional(),
// Query parameters
parameters: z.object({
relationship_types: z.array(z.string()).optional(),
max_depth: z.number().min(1).max(10).default(3),
include_metadata: z.boolean().default(true),
filter_by_status: z.array(z.string()).optional(),
min_relevance_score: z.number().min(0).max(1).optional()
}).optional(),
// Traversal direction
direction: z.enum(['forward', 'backward', 'bidirectional']).default('bidirectional'),
// Result limits
limit: z.number().min(1).max(1000).default(100)
});
// Graph result schema
export const GraphResultSchema = z.object({
nodes: z.array(z.object({
id: z.string(),
type: z.string(),
data: z.any(),
metadata: z.object({
created_at: z.date(),
updated_at: z.date(),
access_count: z.number().default(0),
relevance_score: z.number().min(0).max(1).optional()
})
})),
edges: z.array(z.object({
source_id: z.string(),
target_id: z.string(),
relationship_type: z.string(),
description: z.string().optional(),
weight: z.number().min(0).max(1).default(1),
metadata: z.object({
created_at: z.date(),
last_traversed: z.date().optional(),
traversal_count: z.number().default(0)
})
})),
query_metadata: z.object({
total_nodes: z.number(),
total_edges: z.number(),
traversal_depth: z.number(),
processing_time_ms: z.number(),
cache_used: z.boolean()
})
});
// Workspace context schema
export const WorkspaceContextSchema = z.object({
workspace_id: z.string(),
project_id: z.string(),
// Product context (static, high-level information)
product_context: z.object({
project_overview: z.string(),
architecture_decisions: z.array(z.string()),
tech_stack: z.array(z.string()),
business_requirements: z.array(z.string()),
constraints: z.array(z.string())
}),
// Active context (dynamic, session-specific)
active_context: z.object({
current_features: z.array(z.string()),
active_issues: z.array(z.string()),
recent_changes: z.array(z.object({
change_id: z.string(),
description: z.string(),
timestamp: z.date(),
impact_level: z.enum(['low', 'medium', 'high'])
})),
session_goals: z.array(z.string())
}),
// Access control
access_control: z.object({
workspace_type: z.enum(['private', 'team', 'organization', 'public']),
access_level: z.enum(['read', 'write', 'admin']),
allowed_users: z.array(z.string()).optional(),
sharing_settings: z.object({
allow_cross_workspace: z.boolean().default(false),
public_patterns: z.boolean().default(false)
})
}),
metadata: z.object({
created_at: z.date(),
updated_at: z.date(),
last_accessed: z.date(),
version: z.number().default(1)
})
});
/**
* Knowledge Graph Manager - Context Portal Integration
*/
export class KnowledgeGraphManager {
mongoManager;
constructor() {
this.mongoManager = getConnectionManager();
}
/**
* Initialize workspace with Context Portal patterns
*/
async initializeWorkspace(workspaceId, projectId, initialContext) {
const startTime = Date.now();
// Security check
const securityResult = await securityManager.processInput(JSON.stringify(initialContext), { source: 'api', agent_type: 'system' });
if (securityResult.blocked) {
throw new Error(`Workspace initialization blocked: ${securityResult.security_flags.join(', ')}`);
}
const workspace = {
workspace_id: workspaceId,
project_id: projectId,
product_context: {
project_overview: '',
architecture_decisions: [],
tech_stack: [],
business_requirements: [],
constraints: [],
...initialContext.product_context
},
active_context: {
current_features: [],
active_issues: [],
recent_changes: [],
session_goals: [],
...initialContext.active_context
},
access_control: {
workspace_type: 'private',
access_level: 'admin',
sharing_settings: {
allow_cross_workspace: false,
public_patterns: false
},
...initialContext.access_control
},
metadata: {
created_at: new Date(),
updated_at: new Date(),
last_accessed: new Date(),
version: 1
}
};
// Store in MongoDB
const db = this.mongoManager.getDatabase();
await db.collection(COLLECTIONS.WORKSPACES).insertOne(workspace);
console.log(`ποΈ Workspace ${workspaceId} initialized in ${Date.now() - startTime}ms`);
return workspace;
}
/**
* Create decision with Context Portal patterns
*/
async createDecision(workspaceId, decision) {
const newDecision = {
id: new ObjectId().toString(),
workspace_id: workspaceId,
date: new Date(),
...decision
};
// Security processing
const securityResult = await securityManager.processInput(`${decision.title} ${decision.description} ${decision.rationale}`, { source: 'user', agent_type: 'generic' });
if (securityResult.blocked) {
throw new Error(`Decision creation blocked: ${securityResult.security_flags.join(', ')}`);
}
// Store decision
const db = this.mongoManager.getDatabase();
await db.collection(COLLECTIONS.DECISIONS).insertOne(newDecision);
// Auto-link to related progress entries (Context Portal pattern)
await this.autoLinkDecisionToProgress(newDecision);
console.log(`π Decision created: ${newDecision.title}`);
return newDecision;
}
/**
* Create progress entry with hierarchical relationships
*/
async createProgressEntry(workspaceId, progress) {
const newProgress = {
id: new ObjectId().toString(),
workspace_id: workspaceId,
date: new Date(),
...progress
};
// Store progress entry
const db = this.mongoManager.getDatabase();
await db.collection(COLLECTIONS.PROGRESS_ENTRIES).insertOne(newProgress);
// Create hierarchical links if parent exists
if (newProgress.parent_id) {
await this.createContextLink(workspaceId, {
source_item_type: 'progress_entry',
source_item_id: newProgress.parent_id,
target_item_type: 'progress_entry',
target_item_id: newProgress.id,
relationship_type: 'enables',
description: 'Parent-child progress relationship'
});
}
console.log(`β
Progress entry created: ${newProgress.task}`);
return newProgress;
}
/**
* Create system pattern with usage examples and trade-offs
*/
async createSystemPattern(workspaceId, pattern) {
const newPattern = {
id: new ObjectId().toString(),
workspace_id: workspaceId,
...pattern
};
// Store system pattern
const db = this.mongoManager.getDatabase();
await db.collection(COLLECTIONS.SYSTEM_PATTERNS).insertOne(newPattern);
console.log(`π§ System pattern created: ${newPattern.pattern_name}`);
return newPattern;
}
/**
* Create explicit context link (Context Portal core pattern)
*/
async createContextLink(workspaceId, link) {
const newLink = {
workspace_id: workspaceId,
timestamp: new Date(),
...link
};
// Validate entities exist
await this.validateLinkEntities(newLink);
// Store context link
const db = this.mongoManager.getDatabase();
await db.collection(COLLECTIONS.CONTEXT_LINKS).insertOne(newLink);
console.log(`π Context link created: ${link.source_item_type}:${link.source_item_id} β ${link.target_item_type}:${link.target_item_id} (${link.relationship_type})`);
return newLink;
}
/**
* Query knowledge graph with Context Portal patterns
*/
async queryGraph(query) {
const startTime = Date.now();
// Use performance optimizer for complex queries
const result = await performanceOptimizer.processTask({
type: 'search',
input_data: query,
context: { workspace_id: query.workspace_id }
}, async (task) => {
return await this.executeGraphQuery(task.input_data);
});
const processingTime = Date.now() - startTime;
console.log(`πΈοΈ Graph query completed in ${processingTime}ms`);
return result.result;
}
/**
* Execute graph query with optimized traversal
*/
async executeGraphQuery(query) {
const db = this.mongoManager.getDatabase();
const nodes = [];
const edges = [];
const visitedNodes = new Set();
const maxDepth = query.parameters?.max_depth || 3;
let currentDepth = 0;
let nodesToProcess = query.source ? [`${query.source.item_type}:${query.source.item_id}`] : [];
// If no source, start with pattern search
if (!query.source && query.query_type === 'pattern_search') {
const patterns = await this.findPatterns(query);
nodesToProcess = patterns.map(p => `system_pattern:${p.id}`);
}
// Breadth-first traversal
while (nodesToProcess.length > 0 && currentDepth < maxDepth) {
const nextNodes = [];
for (const nodeId of nodesToProcess) {
if (visitedNodes.has(nodeId))
continue;
visitedNodes.add(nodeId);
// Load node data
const nodeData = await this.loadNodeData(nodeId, query.workspace_id);
if (nodeData) {
nodes.push(nodeData);
// Find connected nodes
const connections = await this.findConnections(nodeId, query.workspace_id, query.direction, query.parameters?.relationship_types);
for (const connection of connections) {
edges.push(connection);
// Add target nodes for next iteration
const targetId = `${connection.target_id}`;
if (!visitedNodes.has(targetId)) {
nextNodes.push(targetId);
}
}
}
}
nodesToProcess = nextNodes;
currentDepth++;
}
return {
nodes,
edges,
query_metadata: {
total_nodes: nodes.length,
total_edges: edges.length,
traversal_depth: currentDepth,
processing_time_ms: 0, // Will be set by caller
cache_used: false // Simplified
}
};
}
/**
* Load node data by ID and type
*/
async loadNodeData(nodeId, workspaceId) {
const [itemType, itemId] = nodeId.split(':');
const db = this.mongoManager.getDatabase();
let collection;
switch (itemType) {
case 'decision':
collection = COLLECTIONS.DECISIONS;
break;
case 'progress_entry':
collection = COLLECTIONS.PROGRESS_ENTRIES;
break;
case 'system_pattern':
collection = COLLECTIONS.SYSTEM_PATTERNS;
break;
default:
return null;
}
const data = await db.collection(collection).findOne({
id: itemId,
workspace_id: workspaceId
});
if (!data)
return null;
return {
id: nodeId,
type: itemType,
data: data,
metadata: {
created_at: data.date || data.created_at || new Date(),
updated_at: data.updated_at || new Date(),
access_count: 0
}
};
}
/**
* Find connections for a node
*/
async findConnections(nodeId, workspaceId, direction, relationshipTypes) {
const [itemType, itemId] = nodeId.split(':');
const db = this.mongoManager.getDatabase();
const query = { workspace_id: workspaceId };
// Build query based on direction
if (direction === 'forward' || direction === 'bidirectional') {
query.$or = [
{ source_item_type: itemType, source_item_id: itemId }
];
}
if (direction === 'backward' || direction === 'bidirectional') {
if (query.$or) {
query.$or.push({ target_item_type: itemType, target_item_id: itemId });
}
else {
query.$or = [{ target_item_type: itemType, target_item_id: itemId }];
}
}
// Filter by relationship types
if (relationshipTypes && relationshipTypes.length > 0) {
query.relationship_type = { $in: relationshipTypes };
}
const links = await db.collection(COLLECTIONS.CONTEXT_LINKS).find(query).toArray();
return links.map(link => ({
source_id: `${link.source_item_type}:${link.source_item_id}`,
target_id: `${link.target_item_type}:${link.target_item_id}`,
relationship_type: link.relationship_type,
description: link.description,
weight: 1.0, // Simplified
metadata: {
created_at: link.timestamp,
traversal_count: 0
}
}));
}
/**
* Find patterns matching query
*/
async findPatterns(query) {
const db = this.mongoManager.getDatabase();
const patterns = await db.collection(COLLECTIONS.SYSTEM_PATTERNS)
.find({ workspace_id: query.workspace_id })
.limit(query.limit)
.toArray();
return patterns;
}
/**
* Auto-link decisions to related progress entries (Context Portal pattern)
*/
async autoLinkDecisionToProgress(decision) {
const db = this.mongoManager.getDatabase();
// Find progress entries with similar keywords
const keywords = this.extractKeywords(`${decision.title} ${decision.description}`);
const relatedProgress = await db.collection(COLLECTIONS.PROGRESS_ENTRIES)
.find({
workspace_id: decision.workspace_id,
$or: keywords.map(keyword => ({
$or: [
{ task: { $regex: keyword, $options: 'i' } },
{ progress_notes: { $regex: keyword, $options: 'i' } }
]
}))
})
.limit(5)
.toArray();
// Create context links
for (const progress of relatedProgress) {
await this.createContextLink(decision.workspace_id, {
source_item_type: 'decision',
source_item_id: decision.id,
target_item_type: 'progress_entry',
target_item_id: progress.id,
relationship_type: 'relates_to_progress',
description: 'Auto-linked based on content similarity'
});
}
}
/**
* Validate that link entities exist
*/
async validateLinkEntities(link) {
const db = this.mongoManager.getDatabase();
// Validate source entity
const sourceExists = await this.entityExists(link.workspace_id, link.source_item_type, link.source_item_id);
if (!sourceExists) {
throw new Error(`Source entity not found: ${link.source_item_type}:${link.source_item_id}`);
}
// Validate target entity
const targetExists = await this.entityExists(link.workspace_id, link.target_item_type, link.target_item_id);
if (!targetExists) {
throw new Error(`Target entity not found: ${link.target_item_type}:${link.target_item_id}`);
}
}
/**
* Check if entity exists
*/
async entityExists(workspaceId, itemType, itemId) {
const db = this.mongoManager.getDatabase();
let collection;
switch (itemType) {
case 'decision':
collection = COLLECTIONS.DECISIONS;
break;
case 'progress_entry':
collection = COLLECTIONS.PROGRESS_ENTRIES;
break;
case 'system_pattern':
collection = COLLECTIONS.SYSTEM_PATTERNS;
break;
case 'context_pattern':
collection = COLLECTIONS.CONTEXT_PATTERNS;
break;
default:
return false;
}
const count = await db.collection(collection).countDocuments({
id: itemId,
workspace_id: workspaceId
});
return count > 0;
}
/**
* Extract keywords for auto-linking
*/
extractKeywords(text) {
const words = text.toLowerCase()
.replace(/[^\w\s]/g, ' ')
.split(/\s+/)
.filter(word => word.length > 3);
// Remove common stop words
const stopWords = new Set([
'this', 'that', 'with', 'have', 'will', 'from', 'they', 'been',
'have', 'were', 'said', 'each', 'which', 'their', 'time'
]);
const keywords = words.filter(word => !stopWords.has(word));
// Return top 10 most relevant keywords
return Array.from(new Set(keywords)).slice(0, 10);
}
/**
* Get workspace analytics and health metrics
*/
async getWorkspaceAnalytics(workspaceId) {
const db = this.mongoManager.getDatabase();
// Count entities
const [decisions, progress, patterns, links] = await Promise.all([
db.collection(COLLECTIONS.DECISIONS).countDocuments({ workspace_id: workspaceId }),
db.collection(COLLECTIONS.PROGRESS_ENTRIES).countDocuments({ workspace_id: workspaceId }),
db.collection(COLLECTIONS.SYSTEM_PATTERNS).countDocuments({ workspace_id: workspaceId }),
db.collection(COLLECTIONS.CONTEXT_LINKS).countDocuments({ workspace_id: workspaceId })
]);
// Get relationship statistics
const relationshipStats = await db.collection(COLLECTIONS.CONTEXT_LINKS)
.aggregate([
{ $match: { workspace_id: workspaceId } },
{ $group: { _id: '$relationship_type', count: { $sum: 1 } } }
]).toArray();
const relationshipCounts = relationshipStats.reduce((acc, stat) => {
acc[stat._id] = stat.count;
return acc;
}, {});
// Calculate health score (simplified)
const totalEntities = decisions + progress + patterns;
const connectivityRatio = totalEntities > 0 ? links / totalEntities : 0;
const healthScore = Math.min(connectivityRatio * 0.7 + (totalEntities > 10 ? 0.3 : 0.1), 1.0);
return {
entity_counts: {
decisions,
progress_entries: progress,
system_patterns: patterns,
context_links: links
},
relationship_stats: relationshipCounts,
activity_metrics: {
daily_changes: 0, // Would be calculated from history
decision_velocity: 0, // Decisions per week
pattern_reuse: 0 // Pattern usage frequency
},
health_score: healthScore
};
}
/**
* Export workspace knowledge graph
*/
async exportWorkspaceGraph(workspaceId, format = 'json') {
const query = {
workspace_id: workspaceId,
query_type: 'traverse',
parameters: {
max_depth: 10
},
limit: 10000
};
const graphResult = await this.queryGraph(query);
switch (format) {
case 'json':
return {
nodes: graphResult.nodes,
edges: graphResult.edges,
metadata: graphResult.query_metadata,
exported_at: new Date()
};
case 'cypher':
return this.convertToCypher(graphResult);
case 'graphml':
return this.convertToGraphML(graphResult);
default:
throw new Error(`Unsupported export format: ${format}`);
}
}
/**
* Convert graph result to Cypher format
*/
convertToCypher(graph) {
let cypher = '// Workspace Knowledge Graph Export\n';
// Create nodes
for (const node of graph.nodes) {
cypher += `CREATE (${node.id.replace(':', '_')}:${node.type} {`;
cypher += `id: '${node.data.id}', `;
cypher += `title: '${node.data.title || node.data.task || node.data.pattern_name}', `;
cypher += `created_at: '${node.metadata.created_at}'`;
cypher += '})\n';
}
// Create relationships
for (const edge of graph.edges) {
const sourceId = edge.source_id.replace(':', '_');
const targetId = edge.target_id.replace(':', '_');
cypher += `CREATE (${sourceId})-[:${edge.relationship_type.toUpperCase()}]->(${targetId})\n`;
}
return cypher;
}
/**
* Convert graph result to GraphML format
*/
convertToGraphML(graph) {
let graphml = '<?xml version="1.0" encoding="UTF-8"?>\n';
graphml += '<graphml xmlns="http://graphml.graphdrawing.org/xmlns">\n';
graphml += ' <graph id="workspace_graph" edgedefault="directed">\n';
// Add nodes
for (const node of graph.nodes) {
graphml += ` <node id="${node.id}">\n`;
graphml += ` <data key="type">${node.type}</data>\n`;
graphml += ` <data key="title">${node.data.title || node.data.task || node.data.pattern_name}</data>\n`;
graphml += ' </node>\n';
}
// Add edges
for (const edge of graph.edges) {
graphml += ` <edge source="${edge.source_id}" target="${edge.target_id}">\n`;
graphml += ` <data key="relationship">${edge.relationship_type}</data>\n`;
graphml += ' </edge>\n';
}
graphml += ' </graph>\n';
graphml += '</graphml>';
return graphml;
}
}
// Export singleton instance
export const knowledgeGraphManager = new KnowledgeGraphManager();