@4da/mcp-server 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +135 -0
  2. package/dist/db.d.ts +64 -0
  3. package/dist/db.d.ts.map +1 -0
  4. package/dist/db.js +578 -0
  5. package/dist/db.js.map +1 -0
  6. package/dist/index.d.ts +37 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +422 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/llm.d.ts +144 -0
  11. package/dist/llm.d.ts.map +1 -0
  12. package/dist/llm.js +447 -0
  13. package/dist/llm.js.map +1 -0
  14. package/dist/output-manager.d.ts +156 -0
  15. package/dist/output-manager.d.ts.map +1 -0
  16. package/dist/output-manager.js +156 -0
  17. package/dist/output-manager.js.map +1 -0
  18. package/dist/schema-registry.d.ts +46 -0
  19. package/dist/schema-registry.d.ts.map +1 -0
  20. package/dist/schema-registry.js +133 -0
  21. package/dist/schema-registry.js.map +1 -0
  22. package/dist/schemas/config-validator.json +18 -0
  23. package/dist/schemas/context-analysis.json +25 -0
  24. package/dist/schemas/daily-briefing.json +34 -0
  25. package/dist/schemas/explain-relevance.json +19 -0
  26. package/dist/schemas/get-actionable-signals.json +29 -0
  27. package/dist/schemas/get-context.json +17 -0
  28. package/dist/schemas/get-relevant-content.json +26 -0
  29. package/dist/schemas/llm-status.json +13 -0
  30. package/dist/schemas/record-feedback.json +24 -0
  31. package/dist/schemas/score-autopsy.json +30 -0
  32. package/dist/schemas/source-health.json +17 -0
  33. package/dist/schemas/topic-connections.json +34 -0
  34. package/dist/schemas/trend-analysis.json +29 -0
  35. package/dist/tools/attention-report.d.ts +39 -0
  36. package/dist/tools/attention-report.d.ts.map +1 -0
  37. package/dist/tools/attention-report.js +72 -0
  38. package/dist/tools/attention-report.js.map +1 -0
  39. package/dist/tools/config-validator.d.ts +59 -0
  40. package/dist/tools/config-validator.d.ts.map +1 -0
  41. package/dist/tools/config-validator.js +375 -0
  42. package/dist/tools/config-validator.js.map +1 -0
  43. package/dist/tools/context-analysis.d.ts +108 -0
  44. package/dist/tools/context-analysis.d.ts.map +1 -0
  45. package/dist/tools/context-analysis.js +300 -0
  46. package/dist/tools/context-analysis.js.map +1 -0
  47. package/dist/tools/daily-briefing.d.ts +103 -0
  48. package/dist/tools/daily-briefing.d.ts.map +1 -0
  49. package/dist/tools/daily-briefing.js +278 -0
  50. package/dist/tools/daily-briefing.js.map +1 -0
  51. package/dist/tools/explain-relevance.d.ts +36 -0
  52. package/dist/tools/explain-relevance.d.ts.map +1 -0
  53. package/dist/tools/explain-relevance.js +50 -0
  54. package/dist/tools/explain-relevance.js.map +1 -0
  55. package/dist/tools/export-context.d.ts +43 -0
  56. package/dist/tools/export-context.d.ts.map +1 -0
  57. package/dist/tools/export-context.js +104 -0
  58. package/dist/tools/export-context.js.map +1 -0
  59. package/dist/tools/get-actionable-signals.d.ts +65 -0
  60. package/dist/tools/get-actionable-signals.d.ts.map +1 -0
  61. package/dist/tools/get-actionable-signals.js +268 -0
  62. package/dist/tools/get-actionable-signals.js.map +1 -0
  63. package/dist/tools/get-context.d.ts +34 -0
  64. package/dist/tools/get-context.d.ts.map +1 -0
  65. package/dist/tools/get-context.js +43 -0
  66. package/dist/tools/get-context.js.map +1 -0
  67. package/dist/tools/get-relevant-content.d.ts +44 -0
  68. package/dist/tools/get-relevant-content.d.ts.map +1 -0
  69. package/dist/tools/get-relevant-content.js +56 -0
  70. package/dist/tools/get-relevant-content.js.map +1 -0
  71. package/dist/tools/index.d.ts +40 -0
  72. package/dist/tools/index.d.ts.map +1 -0
  73. package/dist/tools/index.js +44 -0
  74. package/dist/tools/index.js.map +1 -0
  75. package/dist/tools/knowledge-gaps.d.ts +36 -0
  76. package/dist/tools/knowledge-gaps.d.ts.map +1 -0
  77. package/dist/tools/knowledge-gaps.js +76 -0
  78. package/dist/tools/knowledge-gaps.js.map +1 -0
  79. package/dist/tools/llm-status.d.ts +45 -0
  80. package/dist/tools/llm-status.d.ts.map +1 -0
  81. package/dist/tools/llm-status.js +92 -0
  82. package/dist/tools/llm-status.js.map +1 -0
  83. package/dist/tools/project-health.d.ts +41 -0
  84. package/dist/tools/project-health.d.ts.map +1 -0
  85. package/dist/tools/project-health.js +71 -0
  86. package/dist/tools/project-health.js.map +1 -0
  87. package/dist/tools/record-feedback.d.ts +39 -0
  88. package/dist/tools/record-feedback.d.ts.map +1 -0
  89. package/dist/tools/record-feedback.js +60 -0
  90. package/dist/tools/record-feedback.js.map +1 -0
  91. package/dist/tools/reverse-mentions.d.ts +38 -0
  92. package/dist/tools/reverse-mentions.d.ts.map +1 -0
  93. package/dist/tools/reverse-mentions.js +57 -0
  94. package/dist/tools/reverse-mentions.js.map +1 -0
  95. package/dist/tools/score-autopsy.d.ts +93 -0
  96. package/dist/tools/score-autopsy.d.ts.map +1 -0
  97. package/dist/tools/score-autopsy.js +288 -0
  98. package/dist/tools/score-autopsy.js.map +1 -0
  99. package/dist/tools/semantic-shifts.d.ts +37 -0
  100. package/dist/tools/semantic-shifts.d.ts.map +1 -0
  101. package/dist/tools/semantic-shifts.js +73 -0
  102. package/dist/tools/semantic-shifts.js.map +1 -0
  103. package/dist/tools/signal-chains.d.ts +45 -0
  104. package/dist/tools/signal-chains.d.ts.map +1 -0
  105. package/dist/tools/signal-chains.js +60 -0
  106. package/dist/tools/signal-chains.js.map +1 -0
  107. package/dist/tools/source-health.d.ts +64 -0
  108. package/dist/tools/source-health.d.ts.map +1 -0
  109. package/dist/tools/source-health.js +176 -0
  110. package/dist/tools/source-health.js.map +1 -0
  111. package/dist/tools/topic-connections.d.ts +112 -0
  112. package/dist/tools/topic-connections.d.ts.map +1 -0
  113. package/dist/tools/topic-connections.js +318 -0
  114. package/dist/tools/topic-connections.js.map +1 -0
  115. package/dist/tools/trend-analysis.d.ts +105 -0
  116. package/dist/tools/trend-analysis.d.ts.map +1 -0
  117. package/dist/tools/trend-analysis.js +295 -0
  118. package/dist/tools/trend-analysis.js.map +1 -0
  119. package/dist/types.d.ts +163 -0
  120. package/dist/types.d.ts.map +1 -0
  121. package/dist/types.js +7 -0
  122. package/dist/types.js.map +1 -0
  123. package/package.json +61 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Trend Analysis Tool
3
+ *
4
+ * Statistical analysis of patterns and trends over time.
5
+ * This is a SUPERPOWER - it reveals what's rising, falling, and anomalous.
6
+ *
7
+ * With synthesize=true, uses LLM to interpret trends and make predictions.
8
+ */
9
+ import type { FourDADatabase } from "../db.js";
10
+ import { type CompactResult, type TrendAnalysisKeyData } from "../output-manager.js";
11
+ export declare const trendAnalysisTool: {
12
+ name: string;
13
+ description: string;
14
+ inputSchema: {
15
+ type: string;
16
+ properties: {
17
+ days: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ topic: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ detect_anomalies: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ synthesize: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ compact: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ };
38
+ };
39
+ };
40
+ export interface TrendAnalysisParams {
41
+ days?: number;
42
+ topic?: string;
43
+ detect_anomalies?: boolean;
44
+ synthesize?: boolean;
45
+ compact?: boolean;
46
+ }
47
+ interface TopicTrend {
48
+ topic: string;
49
+ current_week: number;
50
+ previous_week: number;
51
+ change_percent: number;
52
+ trend: "rising" | "falling" | "stable";
53
+ avg_score: number;
54
+ }
55
+ interface VolumeAnomaly {
56
+ date: string;
57
+ volume: number;
58
+ expected: number;
59
+ z_score: number;
60
+ status: "spike" | "drop" | "normal";
61
+ }
62
+ interface SourceTrend {
63
+ source: string;
64
+ volume_trend: "up" | "down" | "stable";
65
+ quality_trend: "up" | "down" | "stable";
66
+ avg_score: number;
67
+ item_count: number;
68
+ }
69
+ interface TrendResult {
70
+ period: {
71
+ start: string;
72
+ end: string;
73
+ days: number;
74
+ };
75
+ summary: {
76
+ total_items: number;
77
+ avg_relevance: number;
78
+ volume_trend: string;
79
+ top_rising_topic: string | null;
80
+ top_falling_topic: string | null;
81
+ };
82
+ topic_trends: TopicTrend[];
83
+ volume_by_day: {
84
+ date: string;
85
+ count: number;
86
+ }[];
87
+ anomalies: VolumeAnomaly[];
88
+ source_trends: SourceTrend[];
89
+ correlations: {
90
+ topic_a: string;
91
+ topic_b: string;
92
+ co_occurrences: number;
93
+ }[];
94
+ predictions: string[];
95
+ ai_interpretation?: {
96
+ narrative: string;
97
+ key_signal: string;
98
+ forecast: string;
99
+ recommended_focus: string;
100
+ model_used: string;
101
+ };
102
+ }
103
+ export declare function executeTrendAnalysis(db: FourDADatabase, params: TrendAnalysisParams): Promise<TrendResult | CompactResult<TrendAnalysisKeyData>>;
104
+ export {};
105
+ //# sourceMappingURL=trend-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/trend-analysis.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EAA8B,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuC7B,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;CACrC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IACvC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IACF,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,iBAAiB,CAAC,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAkJ5D"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Trend Analysis Tool
3
+ *
4
+ * Statistical analysis of patterns and trends over time.
5
+ * This is a SUPERPOWER - it reveals what's rising, falling, and anomalous.
6
+ *
7
+ * With synthesize=true, uses LLM to interpret trends and make predictions.
8
+ */
9
+ import { getLLMConfig, canSynthesize, synthesize, SYNTHESIS_PROMPTS } from "../llm.js";
10
+ import { createTrendAnalysisCompact } from "../output-manager.js";
11
+ export const trendAnalysisTool = {
12
+ name: "trend_analysis",
13
+ description: `Analyze patterns and trends in 4DA's content over time.
14
+
15
+ With synthesize=true (recommended), uses AI to interpret trends and predict what matters.
16
+
17
+ Returns:
18
+ - Topic frequency trends (rising/falling)
19
+ - Volume anomalies detected
20
+ - Week-over-week comparisons
21
+ - Source performance trends
22
+ - AI predictions (when enabled)
23
+
24
+ Use this to understand what's changing in your information landscape.`,
25
+ inputSchema: {
26
+ type: "object",
27
+ properties: {
28
+ days: {
29
+ type: "number",
30
+ description: "Analysis period in days (default: 30)",
31
+ },
32
+ topic: {
33
+ type: "string",
34
+ description: "Specific topic to analyze (optional)",
35
+ },
36
+ detect_anomalies: {
37
+ type: "boolean",
38
+ description: "Include anomaly detection (default: true)",
39
+ },
40
+ synthesize: {
41
+ type: "boolean",
42
+ description: "Use AI to interpret trends and predict (default: true if LLM configured)",
43
+ },
44
+ compact: {
45
+ type: "boolean",
46
+ description: "Return compact result with file reference (default: true for ~80% token reduction)",
47
+ },
48
+ },
49
+ },
50
+ };
51
+ export async function executeTrendAnalysis(db, params) {
52
+ const { days = 30, topic, detect_anomalies = true } = params;
53
+ const useCompact = params.compact !== false; // Default to compact=true
54
+ const dbInstance = db.db;
55
+ // Check LLM availability
56
+ const llmConfig = getLLMConfig(dbInstance);
57
+ const shouldSynthesize = params.synthesize ?? canSynthesize(llmConfig);
58
+ const endDate = new Date();
59
+ const startDate = new Date(endDate.getTime() - days * 24 * 60 * 60 * 1000);
60
+ // Volume by day
61
+ const volumeByDayStmt = dbInstance.prepare(`
62
+ SELECT date(created_at) as date, COUNT(*) as count
63
+ FROM source_items
64
+ WHERE datetime(created_at) >= datetime(?)
65
+ GROUP BY date(created_at)
66
+ ORDER BY date
67
+ `);
68
+ const volumeByDay = volumeByDayStmt.all(startDate.toISOString());
69
+ // Calculate statistics for anomaly detection
70
+ const volumes = volumeByDay.map(v => v.count);
71
+ const mean = volumes.reduce((a, b) => a + b, 0) / volumes.length || 0;
72
+ const stdDev = Math.sqrt(volumes.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / volumes.length) || 1;
73
+ // Detect anomalies
74
+ const anomalies = detect_anomalies
75
+ ? volumeByDay
76
+ .map(v => ({
77
+ date: v.date,
78
+ volume: v.count,
79
+ expected: Math.round(mean),
80
+ z_score: Math.round(((v.count - mean) / stdDev) * 100) / 100,
81
+ status: (v.count - mean) / stdDev > 2 ? "spike" :
82
+ (v.count - mean) / stdDev < -2 ? "drop" : "normal",
83
+ }))
84
+ .filter(a => a.status !== "normal")
85
+ : [];
86
+ // Topic trends - compare this week vs last week
87
+ const topicTrends = getTopicTrends(dbInstance, topic);
88
+ // Source trends
89
+ const sourceTrends = getSourceTrends(dbInstance, days);
90
+ // Topic correlations (co-occurrence)
91
+ const correlations = getTopicCorrelations(dbInstance, days);
92
+ // Overall stats
93
+ const totalStmt = dbInstance.prepare(`
94
+ SELECT COUNT(*) as total, AVG(CASE WHEN url IS NOT NULL THEN 1 ELSE 0 END) as avg_has_url
95
+ FROM source_items
96
+ WHERE datetime(created_at) >= datetime(?)
97
+ `);
98
+ const totalStats = totalStmt.get(startDate.toISOString());
99
+ // Get relevant items for avg score
100
+ const relevantItems = db.getRelevantContent(0, undefined, 1000, days * 24);
101
+ const avgRelevance = relevantItems.length > 0
102
+ ? relevantItems.reduce((sum, i) => sum + i.relevance_score, 0) / relevantItems.length
103
+ : 0;
104
+ // Volume trend
105
+ const recentVolume = volumeByDay.slice(-7).reduce((sum, v) => sum + v.count, 0);
106
+ const olderVolume = volumeByDay.slice(-14, -7).reduce((sum, v) => sum + v.count, 0);
107
+ const volumeTrend = recentVolume > olderVolume * 1.1 ? "increasing" :
108
+ recentVolume < olderVolume * 0.9 ? "decreasing" : "stable";
109
+ // Generate predictions
110
+ const predictions = generatePredictions(topicTrends, volumeTrend, anomalies);
111
+ const result = {
112
+ period: {
113
+ start: startDate.toISOString().split("T")[0],
114
+ end: endDate.toISOString().split("T")[0],
115
+ days,
116
+ },
117
+ summary: {
118
+ total_items: totalStats.total,
119
+ avg_relevance: Math.round(avgRelevance * 100) / 100,
120
+ volume_trend: volumeTrend,
121
+ top_rising_topic: topicTrends.find(t => t.trend === "rising")?.topic || null,
122
+ top_falling_topic: topicTrends.find(t => t.trend === "falling")?.topic || null,
123
+ },
124
+ topic_trends: topicTrends,
125
+ volume_by_day: volumeByDay,
126
+ anomalies,
127
+ source_trends: sourceTrends,
128
+ correlations,
129
+ predictions,
130
+ };
131
+ // AI Interpretation - the actual superpower
132
+ if (shouldSynthesize && canSynthesize(llmConfig)) {
133
+ try {
134
+ const context = db.getUserContext(true, true);
135
+ const trendData = {
136
+ period: result.period,
137
+ summary: result.summary,
138
+ topic_trends: result.topic_trends.slice(0, 8),
139
+ anomalies: result.anomalies,
140
+ correlations: result.correlations,
141
+ };
142
+ const contextData = {
143
+ interests: context.interests.slice(0, 10),
144
+ tech_stack: context.tech_stack,
145
+ role: context.role,
146
+ };
147
+ const synthesis = await synthesize(llmConfig, {
148
+ system: SYNTHESIS_PROMPTS.trendAnalysis.system,
149
+ prompt: SYNTHESIS_PROMPTS.trendAnalysis.buildPrompt(trendData, contextData),
150
+ max_tokens: 400,
151
+ complexity: SYNTHESIS_PROMPTS.trendAnalysis.complexity,
152
+ });
153
+ // Parse the synthesis
154
+ const lines = synthesis.synthesis.split("\n").filter(l => l.trim());
155
+ const keySignal = lines[0] || "";
156
+ const forecast = lines.find(l => l.toLowerCase().includes("week") || l.toLowerCase().includes("expect") || l.toLowerCase().includes("predict")) || lines[1] || "";
157
+ const focus = lines.find(l => l.toLowerCase().includes("focus") || l.toLowerCase().includes("attention") || l.toLowerCase().includes("should")) || "";
158
+ result.ai_interpretation = {
159
+ narrative: synthesis.synthesis,
160
+ key_signal: keySignal,
161
+ forecast: forecast,
162
+ recommended_focus: focus || "Continue monitoring trends",
163
+ model_used: synthesis.model_used,
164
+ };
165
+ }
166
+ catch (error) {
167
+ console.error("AI interpretation failed:", error);
168
+ }
169
+ }
170
+ // Return compact or full result based on parameter
171
+ if (useCompact) {
172
+ return createTrendAnalysisCompact(result);
173
+ }
174
+ return result;
175
+ }
176
+ function getTopicTrends(db, filterTopic) {
177
+ // Define topics to track
178
+ const topics = filterTopic
179
+ ? [filterTopic]
180
+ : ["rust", "typescript", "python", "ai", "llm", "database", "security", "async", "wasm", "react"];
181
+ const trends = [];
182
+ for (const topic of topics) {
183
+ // This week
184
+ const thisWeekStmt = db.prepare(`
185
+ SELECT COUNT(*) as count, AVG(CASE WHEN url IS NOT NULL THEN 1 ELSE 0 END) as quality
186
+ FROM source_items
187
+ WHERE datetime(created_at) >= datetime('now', '-7 days')
188
+ AND (lower(title) LIKE ? OR lower(content) LIKE ?)
189
+ `);
190
+ const thisWeek = thisWeekStmt.all(`%${topic}%`, `%${topic}%`);
191
+ // Last week
192
+ const lastWeekStmt = db.prepare(`
193
+ SELECT COUNT(*) as count
194
+ FROM source_items
195
+ WHERE datetime(created_at) >= datetime('now', '-14 days')
196
+ AND datetime(created_at) < datetime('now', '-7 days')
197
+ AND (lower(title) LIKE ? OR lower(content) LIKE ?)
198
+ `);
199
+ const lastWeek = lastWeekStmt.all(`%${topic}%`, `%${topic}%`);
200
+ const current = thisWeek[0]?.count || 0;
201
+ const previous = lastWeek[0]?.count || 0;
202
+ const changePercent = previous > 0
203
+ ? Math.round(((current - previous) / previous) * 100)
204
+ : current > 0 ? 100 : 0;
205
+ trends.push({
206
+ topic,
207
+ current_week: current,
208
+ previous_week: previous,
209
+ change_percent: changePercent,
210
+ trend: changePercent > 15 ? "rising" : changePercent < -15 ? "falling" : "stable",
211
+ avg_score: thisWeek[0]?.quality || 0,
212
+ });
213
+ }
214
+ // Sort by absolute change
215
+ return trends.sort((a, b) => Math.abs(b.change_percent) - Math.abs(a.change_percent));
216
+ }
217
+ function getSourceTrends(db, days) {
218
+ const stmt = db.prepare(`
219
+ SELECT
220
+ source_type,
221
+ COUNT(*) as total,
222
+ SUM(CASE WHEN datetime(created_at) >= datetime('now', '-7 days') THEN 1 ELSE 0 END) as recent,
223
+ SUM(CASE WHEN datetime(created_at) >= datetime('now', '-14 days')
224
+ AND datetime(created_at) < datetime('now', '-7 days') THEN 1 ELSE 0 END) as older
225
+ FROM source_items
226
+ WHERE datetime(created_at) >= datetime('now', '-' || ? || ' days')
227
+ GROUP BY source_type
228
+ `);
229
+ const sources = stmt.all(days);
230
+ return sources.map(s => ({
231
+ source: s.source_type,
232
+ volume_trend: s.recent > s.older * 1.1 ? "up" :
233
+ s.recent < s.older * 0.9 ? "down" : "stable",
234
+ quality_trend: "stable", // Would need more data to compute
235
+ avg_score: 0.6, // Placeholder
236
+ item_count: s.total,
237
+ }));
238
+ }
239
+ function getTopicCorrelations(db, days) {
240
+ const topicPairs = [
241
+ ["rust", "async"],
242
+ ["ai", "llm"],
243
+ ["typescript", "react"],
244
+ ["database", "sql"],
245
+ ["security", "auth"],
246
+ ];
247
+ const correlations = [];
248
+ for (const [a, b] of topicPairs) {
249
+ const stmt = db.prepare(`
250
+ SELECT COUNT(*) as count
251
+ FROM source_items
252
+ WHERE datetime(created_at) >= datetime('now', '-' || ? || ' days')
253
+ AND (lower(title) LIKE ? OR lower(content) LIKE ?)
254
+ AND (lower(title) LIKE ? OR lower(content) LIKE ?)
255
+ `);
256
+ const result = stmt.all(days, `%${a}%`, `%${a}%`, `%${b}%`, `%${b}%`);
257
+ if (result[0]?.count > 0) {
258
+ correlations.push({
259
+ topic_a: a,
260
+ topic_b: b,
261
+ co_occurrences: result[0].count,
262
+ });
263
+ }
264
+ }
265
+ return correlations.sort((a, b) => b.co_occurrences - a.co_occurrences);
266
+ }
267
+ function generatePredictions(trends, volumeTrend, anomalies) {
268
+ const predictions = [];
269
+ // Rising topics
270
+ const rising = trends.filter(t => t.trend === "rising");
271
+ if (rising.length > 0) {
272
+ predictions.push(`"${rising[0].topic}" is trending up (+${rising[0].change_percent}%) - expect more content soon`);
273
+ }
274
+ // Falling topics
275
+ const falling = trends.filter(t => t.trend === "falling");
276
+ if (falling.length > 0) {
277
+ predictions.push(`"${falling[0].topic}" is declining (${falling[0].change_percent}%) - may stabilize or continue dropping`);
278
+ }
279
+ // Volume prediction
280
+ if (volumeTrend === "increasing") {
281
+ predictions.push("Overall content volume is increasing - more items to filter");
282
+ }
283
+ else if (volumeTrend === "decreasing") {
284
+ predictions.push("Content volume is decreasing - sources may need attention");
285
+ }
286
+ // Anomaly-based prediction
287
+ if (anomalies.filter(a => a.status === "spike").length > 2) {
288
+ predictions.push("Multiple volume spikes detected - possibly major news events");
289
+ }
290
+ if (predictions.length === 0) {
291
+ predictions.push("Patterns are stable - no significant changes predicted");
292
+ }
293
+ return predictions;
294
+ }
295
+ //# sourceMappingURL=trend-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend-analysis.js","sourceRoot":"","sources":["../../src/tools/trend-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Type definitions for 4DA MCP Server
3
+ *
4
+ * These types mirror the 4DA database schema for read operations.
5
+ */
6
+ /**
7
+ * A content item from any source (HN, arXiv, Reddit, etc.)
8
+ */
9
+ export interface SourceItem {
10
+ id: number;
11
+ source_type: string;
12
+ source_id: string;
13
+ url: string | null;
14
+ title: string;
15
+ content: string;
16
+ content_hash: string;
17
+ created_at: string;
18
+ last_seen: string;
19
+ }
20
+ /**
21
+ * A relevant content item with computed score
22
+ */
23
+ export interface RelevantItem {
24
+ id: number;
25
+ source_type: string;
26
+ source_id: string;
27
+ url: string | null;
28
+ title: string;
29
+ content: string;
30
+ relevance_score: number;
31
+ created_at: string;
32
+ discovered_ago: string;
33
+ }
34
+ /**
35
+ * Explicit user interest
36
+ */
37
+ export interface Interest {
38
+ id: number;
39
+ topic: string;
40
+ weight: number;
41
+ source: "explicit" | "github" | "import" | "inferred";
42
+ }
43
+ /**
44
+ * Detected technology from ACE
45
+ */
46
+ export interface DetectedTech {
47
+ name: string;
48
+ category: string;
49
+ confidence: number;
50
+ source: string;
51
+ }
52
+ /**
53
+ * Active topic from ACE
54
+ */
55
+ export interface ActiveTopic {
56
+ topic: string;
57
+ weight: number;
58
+ confidence: number;
59
+ source: string;
60
+ last_seen: string;
61
+ }
62
+ /**
63
+ * Learned topic affinity
64
+ */
65
+ export interface TopicAffinity {
66
+ topic: string;
67
+ affinity_score: number;
68
+ confidence: number;
69
+ positive_signals: number;
70
+ negative_signals: number;
71
+ total_exposures: number;
72
+ }
73
+ /**
74
+ * Anti-topic (learned exclusion)
75
+ */
76
+ export interface AntiTopic {
77
+ topic: string;
78
+ rejection_count: number;
79
+ confidence: number;
80
+ auto_detected: boolean;
81
+ user_confirmed: boolean;
82
+ }
83
+ /**
84
+ * Complete user context returned by get_context
85
+ */
86
+ export interface UserContext {
87
+ role: string | null;
88
+ tech_stack: string[];
89
+ domains: string[];
90
+ interests: Interest[];
91
+ exclusions: string[];
92
+ ace?: {
93
+ detected_tech: DetectedTech[];
94
+ active_topics: ActiveTopic[];
95
+ };
96
+ learned?: {
97
+ topic_affinities: TopicAffinity[];
98
+ anti_topics: AntiTopic[];
99
+ };
100
+ }
101
+ /**
102
+ * Score breakdown for explain_relevance
103
+ */
104
+ export interface ScoreBreakdown {
105
+ embedding_similarity: number | null;
106
+ static_match_score: number;
107
+ ace_match_score: number;
108
+ learned_affinity_score: number;
109
+ anti_penalty: number;
110
+ final_score: number;
111
+ }
112
+ /**
113
+ * Matching context elements
114
+ */
115
+ export interface MatchingContext {
116
+ matching_interests: string[];
117
+ matching_tech: string[];
118
+ matching_topics: string[];
119
+ matching_affinities: string[];
120
+ }
121
+ /**
122
+ * Full relevance explanation
123
+ */
124
+ export interface RelevanceExplanation {
125
+ item_id: number;
126
+ source_type: string;
127
+ title: string;
128
+ score_breakdown: ScoreBreakdown;
129
+ matching_context: MatchingContext;
130
+ explanation: string;
131
+ }
132
+ /**
133
+ * Valid feedback action types
134
+ */
135
+ export type FeedbackAction = "click" | "save" | "dismiss" | "mark_irrelevant";
136
+ /**
137
+ * Feedback recording result
138
+ */
139
+ export interface FeedbackResult {
140
+ success: boolean;
141
+ message: string;
142
+ interaction_id?: number;
143
+ }
144
+ export interface GetRelevantContentParams {
145
+ min_score?: number;
146
+ source_type?: string;
147
+ limit?: number;
148
+ since_hours?: number;
149
+ }
150
+ export interface GetContextParams {
151
+ include_ace?: boolean;
152
+ include_learned?: boolean;
153
+ }
154
+ export interface ExplainRelevanceParams {
155
+ item_id: number;
156
+ source_type: string;
157
+ }
158
+ export interface RecordFeedbackParams {
159
+ item_id: number;
160
+ source_type: string;
161
+ action: FeedbackAction;
162
+ }
163
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Type definitions for 4DA MCP Server
3
+ *
4
+ * These types mirror the 4DA database schema for read operations.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@4da/mcp-server",
3
+ "version": "3.2.0",
4
+ "description": "MCP server for 4DA — plug your personalized developer intelligence feed into Claude Code, Cursor, or any MCP host. 13 tools for content filtering, signals, briefings, and knowledge gap detection.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "4da-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc && pnpm run copy-schemas",
17
+ "copy-schemas": "node -e \"const fs=require('fs');const path=require('path');const src='src/schemas';const dst='dist/schemas';if(!fs.existsSync(dst))fs.mkdirSync(dst,{recursive:true});fs.readdirSync(src).filter(f=>f.endsWith('.json')).forEach(f=>fs.copyFileSync(path.join(src,f),path.join(dst,f)))\"",
18
+ "dev": "tsc --watch",
19
+ "start": "node dist/index.js",
20
+ "inspect": "npx @modelcontextprotocol/inspector node dist/index.js",
21
+ "prepublishOnly": "pnpm run build"
22
+ },
23
+ "keywords": [
24
+ "mcp",
25
+ "model-context-protocol",
26
+ "4da",
27
+ "developer-tools",
28
+ "ai-agent",
29
+ "content-filtering",
30
+ "relevance",
31
+ "intelligence",
32
+ "claude-code",
33
+ "cursor",
34
+ "hacker-news",
35
+ "arxiv",
36
+ "developer-productivity"
37
+ ],
38
+ "author": "4DA",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/runyourempire/4da-v3.git",
43
+ "directory": "mcp-4da-server"
44
+ },
45
+ "homepage": "https://github.com/runyourempire/4da-v3#mcp-integration",
46
+ "bugs": {
47
+ "url": "https://github.com/runyourempire/4da-v3/issues"
48
+ },
49
+ "dependencies": {
50
+ "@modelcontextprotocol/sdk": "^1.0.0",
51
+ "better-sqlite3": "^11.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/better-sqlite3": "^7.6.11",
55
+ "@types/node": "^20.11.0",
56
+ "typescript": "^5.3.0"
57
+ },
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ }
61
+ }