@sofianedjerbi/knowledge-tree-mcp
Version:
MCP server for hierarchical project knowledge management
85 lines • 3.21 kB
JavaScript
/**
* Recent knowledge tool implementation
* Shows recently added or modified knowledge entries
*/
import { join } from 'path';
import { RECENT_DEFAULTS } from '../constants/index.js';
import { readFile, getFileStats } from '../utils/index.js';
/**
* Handler for the recent_knowledge tool
*/
export const recentKnowledgeHandler = async (args, context) => {
const { days = RECENT_DEFAULTS.DAYS, limit = RECENT_DEFAULTS.LIMIT, type = RECENT_DEFAULTS.TYPE } = args;
const allEntries = await context.scanKnowledgeTree();
const entries = [];
// Calculate cutoff date by subtracting exact milliseconds
const now = new Date();
const cutoffDate = new Date(now.getTime() - (days * 24 * 60 * 60 * 1000));
// Load entries with file stats
for (const path of allEntries) {
const fullPath = join(context.knowledgeRoot, path);
try {
const content = await readFile(fullPath);
const entry = JSON.parse(content);
const stats = await getFileStats(fullPath);
// Determine if entry is recent
const created = stats.birthtime;
const modified = stats.mtime;
let changeType = "";
let isRecent = false;
// Check if recently created
if (created >= cutoffDate) {
changeType = "added";
isRecent = true;
}
// Check if recently modified (but not newly created)
else if (modified >= cutoffDate && modified.getTime() !== created.getTime()) {
changeType = "modified";
isRecent = true;
}
// Filter by type
if (isRecent && (type === "all" || type === changeType)) {
entries.push({ path, entry, stats, changeType });
}
}
catch (error) {
// Skip invalid entries
}
}
// Sort by modification time (newest first)
entries.sort((a, b) => b.stats.mtime.getTime() - a.stats.mtime.getTime());
// Apply limit
const limitedEntries = entries.slice(0, limit);
const result = {
period: {
days: days,
from: cutoffDate.toISOString(),
to: new Date().toISOString()
},
summary: {
total_changes: entries.length,
showing: limitedEntries.length,
added: entries.filter(e => e.changeType === "added").length,
modified: entries.filter(e => e.changeType === "modified").length
},
entries: limitedEntries.map(e => ({
path: e.path,
priority: e.entry.priority,
problem: e.entry.problem,
solution: e.entry.solution.substring(0, 100) + (e.entry.solution.length > 100 ? '...' : ''),
change_type: e.changeType,
modified_at: e.stats.mtime.toISOString(),
created_at: e.stats.birthtime.toISOString(),
relationships: e.entry.related_to?.length || 0
}))
};
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2),
},
],
};
};
//# sourceMappingURL=recent.js.map