bc-code-intelligence-mcp
Version:
BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows
142 lines • 5.55 kB
JavaScript
/**
* In-Memory Session Storage Implementation
*
* Default session storage that keeps all sessions in memory.
* Sessions are lost when the MCP server restarts.
* Zero configuration required - works out of the box.
*/
export class InMemorySessionStorage {
sessions = new Map();
config;
constructor(config) {
this.config = {
type: 'memory',
retention: {
maxSessions: 50, // Reasonable memory limit
autoCleanup: true,
...config?.retention
},
privacy: {
includeMessages: true,
includeCode: true,
includeFiles: true,
anonymizeContent: false,
...config?.privacy
}
};
}
async createSession(session) {
// Auto-cleanup if needed
if (this.config.retention?.autoCleanup) {
await this.cleanupIfNeeded(session.userId);
}
this.sessions.set(session.sessionId, { ...session });
}
async getSession(sessionId) {
const session = this.sessions.get(sessionId);
return session ? { ...session } : null;
}
async updateSession(session) {
if (!this.sessions.has(session.sessionId)) {
throw new Error(`Session ${session.sessionId} not found`);
}
// Update last activity
session.lastActivity = new Date();
this.sessions.set(session.sessionId, { ...session });
}
async deleteSession(sessionId) {
this.sessions.delete(sessionId);
}
async getUserSessions(userId) {
const userSessions = Array.from(this.sessions.values())
.filter(session => session.userId === userId)
.sort((a, b) => b.lastActivity.getTime() - a.lastActivity.getTime());
return userSessions.map(session => this.toSessionSummary(session));
}
async getActiveSessions(userId) {
const userSessions = await this.getUserSessions(userId);
return userSessions.filter(session => session.status === 'active' || session.status === 'paused');
}
async getSpecialistSessions(specialistId) {
const specialistSessions = Array.from(this.sessions.values())
.filter(session => session.specialistId === specialistId)
.sort((a, b) => b.lastActivity.getTime() - a.lastActivity.getTime());
return specialistSessions.map(session => this.toSessionSummary(session));
}
async cleanupExpiredSessions() {
const now = new Date();
const maxAge = this.config.retention?.maxAge || 7; // Default 7 days
const cutoffTime = new Date(now.getTime() - (maxAge * 24 * 60 * 60 * 1000));
let cleaned = 0;
for (const [sessionId, session] of this.sessions.entries()) {
if (session.lastActivity < cutoffTime) {
this.sessions.delete(sessionId);
cleaned++;
}
}
return cleaned;
}
async getUserSessionCount(userId) {
return Array.from(this.sessions.values())
.filter(session => session.userId === userId)
.length;
}
async cleanupIfNeeded(userId) {
const maxSessions = this.config.retention?.maxSessions || 50;
const userSessions = Array.from(this.sessions.values())
.filter(session => session.userId === userId)
.sort((a, b) => a.lastActivity.getTime() - b.lastActivity.getTime()); // Oldest first
// Remove oldest sessions if over limit
while (userSessions.length >= maxSessions) {
const oldestSession = userSessions.shift();
if (oldestSession) {
this.sessions.delete(oldestSession.sessionId);
}
}
}
toSessionSummary(session) {
return {
sessionId: session.sessionId,
specialistId: session.specialistId,
startTime: session.startTime,
lastActivity: session.lastActivity,
status: session.status,
messageCount: session.messageCount,
primaryTopics: this.extractPrimaryTopics(session),
keyInsights: session.context.recommendations.slice(0, 3) // Top 3 recommendations
};
}
extractPrimaryTopics(session) {
// Extract topics from message metadata
const topics = new Set();
session.messages.forEach(message => {
if (message.metadata?.topics) {
message.metadata.topics.forEach(topic => topics.add(topic));
}
});
// Also include context-based topics
if (session.context.problem) {
topics.add('problem-solving');
}
if (session.context.codebaseContext?.files.length) {
topics.add('code-review');
}
return Array.from(topics).slice(0, 5); // Top 5 topics
}
// Memory usage diagnostics
getMemoryStats() {
const sessionCount = this.sessions.size;
const totalMessages = Array.from(this.sessions.values())
.reduce((sum, session) => sum + session.messageCount, 0);
// Rough memory estimation
const avgSessionSize = 10; // KB per session (rough estimate)
const avgMessageSize = 1; // KB per message (rough estimate)
const memoryUsageKB = (sessionCount * avgSessionSize) + (totalMessages * avgMessageSize);
return {
sessionCount,
totalMessages,
memoryUsageKB
};
}
}
//# sourceMappingURL=in-memory-storage.js.map