@skillsmith/mcp-server 0.4.6 → 0.4.8

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 (196) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +20 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/__tests__/tool-dispatch.test.d.ts +8 -0
  5. package/dist/src/__tests__/tool-dispatch.test.d.ts.map +1 -0
  6. package/dist/src/__tests__/tool-dispatch.test.js +144 -0
  7. package/dist/src/__tests__/tool-dispatch.test.js.map +1 -0
  8. package/dist/src/index.js +31 -2
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/middleware/license.d.ts +23 -0
  11. package/dist/src/middleware/license.d.ts.map +1 -1
  12. package/dist/src/middleware/license.js +28 -0
  13. package/dist/src/middleware/license.js.map +1 -1
  14. package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -1
  15. package/dist/src/middleware/toolFeatureMapping.js +4 -1
  16. package/dist/src/middleware/toolFeatureMapping.js.map +1 -1
  17. package/dist/src/supabase-client.d.ts +24 -0
  18. package/dist/src/supabase-client.d.ts.map +1 -0
  19. package/dist/src/supabase-client.js +63 -0
  20. package/dist/src/supabase-client.js.map +1 -0
  21. package/dist/src/tool-dispatch.d.ts.map +1 -1
  22. package/dist/src/tool-dispatch.js +71 -62
  23. package/dist/src/tool-dispatch.js.map +1 -1
  24. package/dist/src/tools/analytics.d.ts +155 -0
  25. package/dist/src/tools/analytics.d.ts.map +1 -0
  26. package/dist/src/tools/analytics.js +321 -0
  27. package/dist/src/tools/analytics.js.map +1 -0
  28. package/dist/src/tools/analytics.service.d.ts +46 -0
  29. package/dist/src/tools/analytics.service.d.ts.map +1 -0
  30. package/dist/src/tools/analytics.service.js +69 -0
  31. package/dist/src/tools/analytics.service.js.map +1 -0
  32. package/dist/src/tools/analytics.service.test.d.ts +6 -0
  33. package/dist/src/tools/analytics.service.test.d.ts.map +1 -0
  34. package/dist/src/tools/analytics.service.test.js +151 -0
  35. package/dist/src/tools/analytics.service.test.js.map +1 -0
  36. package/dist/src/tools/analytics.stub.d.ts +27 -0
  37. package/dist/src/tools/analytics.stub.d.ts.map +1 -0
  38. package/dist/src/tools/analytics.stub.js +200 -0
  39. package/dist/src/tools/analytics.stub.js.map +1 -0
  40. package/dist/src/tools/analytics.test.d.ts +6 -0
  41. package/dist/src/tools/analytics.test.d.ts.map +1 -0
  42. package/dist/src/tools/analytics.test.js +146 -0
  43. package/dist/src/tools/analytics.test.js.map +1 -0
  44. package/dist/src/tools/analyze.d.ts.map +1 -1
  45. package/dist/src/tools/analyze.js +7 -1
  46. package/dist/src/tools/analyze.js.map +1 -1
  47. package/dist/src/tools/audit-tools.d.ts +172 -0
  48. package/dist/src/tools/audit-tools.d.ts.map +1 -0
  49. package/dist/src/tools/audit-tools.js +187 -0
  50. package/dist/src/tools/audit-tools.js.map +1 -0
  51. package/dist/src/tools/audit-tools.test.d.ts +10 -0
  52. package/dist/src/tools/audit-tools.test.d.ts.map +1 -0
  53. package/dist/src/tools/audit-tools.test.js +147 -0
  54. package/dist/src/tools/audit-tools.test.js.map +1 -0
  55. package/dist/src/tools/compliance-tools.d.ts +103 -0
  56. package/dist/src/tools/compliance-tools.d.ts.map +1 -0
  57. package/dist/src/tools/compliance-tools.js +257 -0
  58. package/dist/src/tools/compliance-tools.js.map +1 -0
  59. package/dist/src/tools/compliance-tools.service.d.ts +19 -0
  60. package/dist/src/tools/compliance-tools.service.d.ts.map +1 -0
  61. package/dist/src/tools/compliance-tools.service.js +107 -0
  62. package/dist/src/tools/compliance-tools.service.js.map +1 -0
  63. package/dist/src/tools/compliance-tools.service.test.d.ts +6 -0
  64. package/dist/src/tools/compliance-tools.service.test.d.ts.map +1 -0
  65. package/dist/src/tools/compliance-tools.service.test.js +140 -0
  66. package/dist/src/tools/compliance-tools.service.test.js.map +1 -0
  67. package/dist/src/tools/compliance-tools.test.d.ts +6 -0
  68. package/dist/src/tools/compliance-tools.test.d.ts.map +1 -0
  69. package/dist/src/tools/compliance-tools.test.js +136 -0
  70. package/dist/src/tools/compliance-tools.test.js.map +1 -0
  71. package/dist/src/tools/get-skill.d.ts.map +1 -1
  72. package/dist/src/tools/get-skill.js +24 -1
  73. package/dist/src/tools/get-skill.js.map +1 -1
  74. package/dist/src/tools/index-local.d.ts.map +1 -1
  75. package/dist/src/tools/index-local.js +4 -0
  76. package/dist/src/tools/index-local.js.map +1 -1
  77. package/dist/src/tools/install.d.ts.map +1 -1
  78. package/dist/src/tools/install.js +2 -0
  79. package/dist/src/tools/install.js.map +1 -1
  80. package/dist/src/tools/install.tool.d.ts +4 -0
  81. package/dist/src/tools/install.tool.d.ts.map +1 -1
  82. package/dist/src/tools/install.tool.js +4 -0
  83. package/dist/src/tools/install.tool.js.map +1 -1
  84. package/dist/src/tools/install.types.d.ts +4 -0
  85. package/dist/src/tools/install.types.d.ts.map +1 -1
  86. package/dist/src/tools/install.types.js +5 -0
  87. package/dist/src/tools/install.types.js.map +1 -1
  88. package/dist/src/tools/integration-tools.d.ts +210 -0
  89. package/dist/src/tools/integration-tools.d.ts.map +1 -0
  90. package/dist/src/tools/integration-tools.js +264 -0
  91. package/dist/src/tools/integration-tools.js.map +1 -0
  92. package/dist/src/tools/integration-tools.service.d.ts +54 -0
  93. package/dist/src/tools/integration-tools.service.d.ts.map +1 -0
  94. package/dist/src/tools/integration-tools.service.js +299 -0
  95. package/dist/src/tools/integration-tools.service.js.map +1 -0
  96. package/dist/src/tools/integration-tools.service.test.d.ts +8 -0
  97. package/dist/src/tools/integration-tools.service.test.d.ts.map +1 -0
  98. package/dist/src/tools/integration-tools.service.test.js +401 -0
  99. package/dist/src/tools/integration-tools.service.test.js.map +1 -0
  100. package/dist/src/tools/integration-tools.stub.d.ts +13 -0
  101. package/dist/src/tools/integration-tools.stub.d.ts.map +1 -0
  102. package/dist/src/tools/integration-tools.stub.js +133 -0
  103. package/dist/src/tools/integration-tools.stub.js.map +1 -0
  104. package/dist/src/tools/integration-tools.test.d.ts +6 -0
  105. package/dist/src/tools/integration-tools.test.d.ts.map +1 -0
  106. package/dist/src/tools/integration-tools.test.js +259 -0
  107. package/dist/src/tools/integration-tools.test.js.map +1 -0
  108. package/dist/src/tools/publish-private.d.ts +60 -0
  109. package/dist/src/tools/publish-private.d.ts.map +1 -0
  110. package/dist/src/tools/publish-private.js +85 -0
  111. package/dist/src/tools/publish-private.js.map +1 -0
  112. package/dist/src/tools/publish-private.test.d.ts +6 -0
  113. package/dist/src/tools/publish-private.test.d.ts.map +1 -0
  114. package/dist/src/tools/publish-private.test.js +118 -0
  115. package/dist/src/tools/publish-private.test.js.map +1 -0
  116. package/dist/src/tools/publish.types.d.ts +2 -2
  117. package/dist/src/tools/rbac-tools.d.ts +180 -0
  118. package/dist/src/tools/rbac-tools.d.ts.map +1 -0
  119. package/dist/src/tools/rbac-tools.js +300 -0
  120. package/dist/src/tools/rbac-tools.js.map +1 -0
  121. package/dist/src/tools/rbac-tools.test.d.ts +6 -0
  122. package/dist/src/tools/rbac-tools.test.d.ts.map +1 -0
  123. package/dist/src/tools/rbac-tools.test.js +299 -0
  124. package/dist/src/tools/rbac-tools.test.js.map +1 -0
  125. package/dist/src/tools/rbac-tools.types.d.ts +70 -0
  126. package/dist/src/tools/rbac-tools.types.d.ts.map +1 -0
  127. package/dist/src/tools/rbac-tools.types.js +119 -0
  128. package/dist/src/tools/rbac-tools.types.js.map +1 -0
  129. package/dist/src/tools/recommend.helpers.d.ts.map +1 -1
  130. package/dist/src/tools/recommend.helpers.js +2 -1
  131. package/dist/src/tools/recommend.helpers.js.map +1 -1
  132. package/dist/src/tools/recommend.js +3 -3
  133. package/dist/src/tools/recommend.js.map +1 -1
  134. package/dist/src/tools/recommend.types.d.ts +3 -3
  135. package/dist/src/tools/registry-tools.d.ts +133 -0
  136. package/dist/src/tools/registry-tools.d.ts.map +1 -0
  137. package/dist/src/tools/registry-tools.js +246 -0
  138. package/dist/src/tools/registry-tools.js.map +1 -0
  139. package/dist/src/tools/registry-tools.test.d.ts +6 -0
  140. package/dist/src/tools/registry-tools.test.d.ts.map +1 -0
  141. package/dist/src/tools/registry-tools.test.js +167 -0
  142. package/dist/src/tools/registry-tools.test.js.map +1 -0
  143. package/dist/src/tools/search.formatter.d.ts.map +1 -1
  144. package/dist/src/tools/search.formatter.js +11 -1
  145. package/dist/src/tools/search.formatter.js.map +1 -1
  146. package/dist/src/tools/skill-audit.d.ts +3 -3
  147. package/dist/src/tools/skill-audit.d.ts.map +1 -1
  148. package/dist/src/tools/skill-audit.js +5 -5
  149. package/dist/src/tools/skill-audit.js.map +1 -1
  150. package/dist/src/tools/skill-audit.test.js +5 -5
  151. package/dist/src/tools/skill-audit.test.js.map +1 -1
  152. package/dist/src/tools/skill-diff.d.ts +2 -2
  153. package/dist/src/tools/skill-rescan.d.ts.map +1 -1
  154. package/dist/src/tools/skill-rescan.js +2 -3
  155. package/dist/src/tools/skill-rescan.js.map +1 -1
  156. package/dist/src/tools/skill-rescan.test.js +2 -2
  157. package/dist/src/tools/skill-rescan.test.js.map +1 -1
  158. package/dist/src/tools/sso-tools.d.ts +136 -0
  159. package/dist/src/tools/sso-tools.d.ts.map +1 -0
  160. package/dist/src/tools/sso-tools.js +214 -0
  161. package/dist/src/tools/sso-tools.js.map +1 -0
  162. package/dist/src/tools/sso-tools.test.d.ts +6 -0
  163. package/dist/src/tools/sso-tools.test.d.ts.map +1 -0
  164. package/dist/src/tools/sso-tools.test.js +167 -0
  165. package/dist/src/tools/sso-tools.test.js.map +1 -0
  166. package/dist/src/tools/suggest.d.ts +4 -4
  167. package/dist/src/tools/suggest.d.ts.map +1 -1
  168. package/dist/src/tools/suggest.js +7 -1
  169. package/dist/src/tools/suggest.js.map +1 -1
  170. package/dist/src/tools/team-workspace.d.ts +179 -0
  171. package/dist/src/tools/team-workspace.d.ts.map +1 -0
  172. package/dist/src/tools/team-workspace.js +243 -0
  173. package/dist/src/tools/team-workspace.js.map +1 -0
  174. package/dist/src/tools/team-workspace.stub.d.ts +13 -0
  175. package/dist/src/tools/team-workspace.stub.d.ts.map +1 -0
  176. package/dist/src/tools/team-workspace.stub.js +76 -0
  177. package/dist/src/tools/team-workspace.stub.js.map +1 -0
  178. package/dist/src/tools/team-workspace.test.d.ts +7 -0
  179. package/dist/src/tools/team-workspace.test.d.ts.map +1 -0
  180. package/dist/src/tools/team-workspace.test.js +273 -0
  181. package/dist/src/tools/team-workspace.test.js.map +1 -0
  182. package/dist/src/tools/uninstall.d.ts +1 -1
  183. package/dist/src/utils/team-resolver.d.ts +20 -0
  184. package/dist/src/utils/team-resolver.d.ts.map +1 -0
  185. package/dist/src/utils/team-resolver.js +52 -0
  186. package/dist/src/utils/team-resolver.js.map +1 -0
  187. package/dist/src/utils/url-validator.d.ts +24 -0
  188. package/dist/src/utils/url-validator.d.ts.map +1 -0
  189. package/dist/src/utils/url-validator.js +59 -0
  190. package/dist/src/utils/url-validator.js.map +1 -0
  191. package/dist/tests/integration/recommend.integration.test.js +1 -1
  192. package/dist/tests/integration/recommend.integration.test.js.map +1 -1
  193. package/dist/tests/recommend.test.js +1 -1
  194. package/dist/tests/recommend.test.js.map +1 -1
  195. package/package.json +3 -3
  196. package/server.json +2 -2
@@ -0,0 +1,321 @@
1
+ /**
2
+ * @fileoverview Analytics MCP tools — team and enterprise usage dashboards
3
+ * @module @skillsmith/mcp-server/tools/analytics
4
+ * @see SMI-3899: Team Usage Analytics MCP Tools (Wave 2b)
5
+ *
6
+ * Split-tier analytics:
7
+ * - Team tier: team_analytics_dashboard, team_usage_report (usage_analytics flag)
8
+ * - Enterprise tier: analytics_dashboard, usage_report (advanced_analytics flag)
9
+ *
10
+ * Uses real SQLite queries against audit_logs when db is available,
11
+ * falls back to stub mock data when no database is present.
12
+ */
13
+ import { z } from 'zod';
14
+ import { periodDays, stubTeamAnalyticsDashboard, stubTeamUsageReport, stubAnalyticsDashboard, stubUsageReport, } from './analytics.stub.js';
15
+ import { createRealAnalyticsService } from './analytics.service.js';
16
+ // Re-export stub helpers for external consumers
17
+ export { periodDays, generateDailyTrend } from './analytics.stub.js';
18
+ /**
19
+ * Resolve analytics service: real (SQLite-backed) when db is available,
20
+ * otherwise null (handlers fall back to inline stub data).
21
+ */
22
+ function resolveAnalyticsService(context) {
23
+ try {
24
+ if (context.db && context.db.open) {
25
+ return createRealAnalyticsService(context.db);
26
+ }
27
+ }
28
+ catch {
29
+ // Fall through to stub
30
+ }
31
+ return null;
32
+ }
33
+ // ============================================================================
34
+ // Shared types
35
+ // ============================================================================
36
+ const periodSchema = z.enum(['7d', '30d', '90d']).optional().default('30d');
37
+ const formatSchema = z.enum(['summary', 'detailed']).optional().default('summary');
38
+ const enterpriseFormatSchema = z.enum(['summary', 'detailed', 'csv']).optional().default('summary');
39
+ // ============================================================================
40
+ // Input schemas
41
+ // ============================================================================
42
+ export const teamAnalyticsDashboardInputSchema = z.object({
43
+ period: periodSchema.describe('Time period for analytics (default 30d)'),
44
+ });
45
+ export const teamUsageReportInputSchema = z.object({
46
+ period: periodSchema.describe('Time period for report (default 30d)'),
47
+ format: formatSchema.describe('Report format: summary or detailed (default summary)'),
48
+ });
49
+ export const analyticsDashboardInputSchema = z.object({
50
+ period: periodSchema.describe('Time period for analytics (default 30d)'),
51
+ includeRecommendations: z
52
+ .boolean()
53
+ .optional()
54
+ .default(false)
55
+ .describe('Include recommendation accuracy metrics'),
56
+ });
57
+ export const usageReportInputSchema = z.object({
58
+ period: periodSchema.describe('Time period for report (default 30d)'),
59
+ format: enterpriseFormatSchema.describe('Report format: summary, detailed, or csv (default summary)'),
60
+ });
61
+ // ============================================================================
62
+ // Tool schemas for MCP registration
63
+ // ============================================================================
64
+ export const teamAnalyticsDashboardToolSchema = {
65
+ name: 'team_analytics_dashboard',
66
+ description: 'View team usage analytics: per-user tool usage counts, top tools, and daily trend. ' +
67
+ 'Requires Team tier (usage_analytics feature).',
68
+ inputSchema: {
69
+ type: 'object',
70
+ properties: {
71
+ period: {
72
+ type: 'string',
73
+ enum: ['7d', '30d', '90d'],
74
+ description: 'Time period (default 30d)',
75
+ },
76
+ },
77
+ },
78
+ };
79
+ export const teamUsageReportToolSchema = {
80
+ name: 'team_usage_report',
81
+ description: 'Generate a weekly/monthly usage summary with period-over-period comparison. ' +
82
+ 'Requires Team tier (usage_analytics feature).',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ period: {
87
+ type: 'string',
88
+ enum: ['7d', '30d', '90d'],
89
+ description: 'Time period (default 30d)',
90
+ },
91
+ format: {
92
+ type: 'string',
93
+ enum: ['summary', 'detailed'],
94
+ description: 'Report format (default summary)',
95
+ },
96
+ },
97
+ },
98
+ };
99
+ export const analyticsDashboardToolSchema = {
100
+ name: 'analytics_dashboard',
101
+ description: 'Enterprise analytics dashboard: recommendation accuracy, skill adoption curves, ' +
102
+ 'team-wide aggregation. Requires Enterprise tier (advanced_analytics feature).',
103
+ inputSchema: {
104
+ type: 'object',
105
+ properties: {
106
+ period: {
107
+ type: 'string',
108
+ enum: ['7d', '30d', '90d'],
109
+ description: 'Time period (default 30d)',
110
+ },
111
+ includeRecommendations: {
112
+ type: 'boolean',
113
+ description: 'Include recommendation accuracy metrics (default false)',
114
+ },
115
+ },
116
+ },
117
+ };
118
+ export const usageReportToolSchema = {
119
+ name: 'usage_report',
120
+ description: 'Comprehensive enterprise usage report with all metrics. ' +
121
+ 'Requires Enterprise tier (advanced_analytics feature).',
122
+ inputSchema: {
123
+ type: 'object',
124
+ properties: {
125
+ period: {
126
+ type: 'string',
127
+ enum: ['7d', '30d', '90d'],
128
+ description: 'Time period (default 30d)',
129
+ },
130
+ format: {
131
+ type: 'string',
132
+ enum: ['summary', 'detailed', 'csv'],
133
+ description: 'Report format (default summary)',
134
+ },
135
+ },
136
+ },
137
+ };
138
+ // ============================================================================
139
+ // Handlers
140
+ // ============================================================================
141
+ /**
142
+ * Team analytics dashboard handler.
143
+ * Returns per-user tool usage, top tools, and daily trend as markdown.
144
+ *
145
+ * Uses real service when db is available, falls back to stub
146
+ */
147
+ export async function executeTeamAnalyticsDashboard(input, context) {
148
+ const days = periodDays(input.period);
149
+ const svc = resolveAnalyticsService(context);
150
+ if (svc) {
151
+ const data = svc.getDashboardData(days);
152
+ const total = data.totalToolCalls;
153
+ const avgPerDay = days > 0 ? (total / days).toFixed(1) : '0.0';
154
+ const lines = [
155
+ `# Team Analytics Dashboard (${input.period})`,
156
+ '',
157
+ '## Summary',
158
+ `- **Period**: Last ${days} days`,
159
+ `- **Total tool calls**: ${total}`,
160
+ `- **Unique tools**: ${data.uniqueTools}`,
161
+ `- **Avg calls/day**: ${avgPerDay}`,
162
+ `- **Data source**: live`,
163
+ '',
164
+ '## Top Tools',
165
+ '| Tool | Calls | % of Total |',
166
+ '|------|-------|------------|',
167
+ ...data.topTools.map((t) => {
168
+ const pct = total > 0 ? Math.round((t.count / total) * 100) : 0;
169
+ return `| ${t.tool} | ${t.count} | ${pct}% |`;
170
+ }),
171
+ '',
172
+ '## Period Comparison',
173
+ `- **Current**: ${data.periodComparison.current}`,
174
+ `- **Previous**: ${data.periodComparison.previous}`,
175
+ `- **Change**: ${data.periodComparison.changePercent >= 0 ? '+' : ''}${data.periodComparison.changePercent}%`,
176
+ '',
177
+ '## Daily Trend (last 7 days)',
178
+ '| Date | Calls |',
179
+ '|------|-------|',
180
+ ...data.dailyTrend.slice(-7).map((d) => `| ${d.date} | ${d.count} |`),
181
+ ];
182
+ return lines.join('\n');
183
+ }
184
+ return stubTeamAnalyticsDashboard(input.period);
185
+ }
186
+ /**
187
+ * Team usage report handler.
188
+ * Returns weekly/monthly summary with period comparison as markdown.
189
+ *
190
+ * Uses real service when db is available, falls back to stub
191
+ */
192
+ export async function executeTeamUsageReport(input, context) {
193
+ const days = periodDays(input.period);
194
+ const svc = resolveAnalyticsService(context);
195
+ if (svc) {
196
+ const data = svc.getUsageReport(days, input.format === 'detailed');
197
+ const { current, previous, changePercent } = data.periodComparison;
198
+ const sign = changePercent >= 0 ? '+' : '';
199
+ const lines = [
200
+ `# Team Usage Report (${input.period})`,
201
+ '',
202
+ '## Period Summary',
203
+ `- **Current period**: ${current} total calls`,
204
+ `- **Previous period**: ${previous} total calls`,
205
+ `- **Change**: ${sign}${changePercent}%`,
206
+ `- **Unique tools**: ${data.uniqueTools}`,
207
+ `- **Data source**: live`,
208
+ '',
209
+ '## Top Tools',
210
+ '| Tool | Calls |',
211
+ '|------|-------|',
212
+ ...data.topTools.map((t) => `| ${t.tool} | ${t.count} |`),
213
+ ];
214
+ if (input.format === 'detailed' && data.byActor) {
215
+ lines.push('', '## Detailed Breakdown by User', '| User | Calls |', '|------|-------|', ...data.byActor.map((a) => `| ${a.actor} | ${a.count} |`));
216
+ }
217
+ return lines.join('\n');
218
+ }
219
+ return stubTeamUsageReport(input.period, input.format);
220
+ }
221
+ /**
222
+ * Enterprise analytics dashboard handler.
223
+ * Returns recommendation accuracy, adoption curves, and team aggregation as markdown.
224
+ *
225
+ * Uses real service when db is available, falls back to stub
226
+ */
227
+ export async function executeAnalyticsDashboard(input, context) {
228
+ const days = periodDays(input.period);
229
+ const svc = resolveAnalyticsService(context);
230
+ if (svc) {
231
+ const data = svc.getDashboardData(days);
232
+ const total = data.totalToolCalls;
233
+ const lines = [
234
+ `# Enterprise Analytics Dashboard (${input.period})`,
235
+ '',
236
+ '## Organization Summary',
237
+ `- **Period**: Last ${days} days`,
238
+ `- **Total tool calls**: ${total}`,
239
+ `- **Unique tools**: ${data.uniqueTools}`,
240
+ `- **Data source**: live`,
241
+ '',
242
+ '## Top Tools',
243
+ '| Tool | Calls | % of Total |',
244
+ '|------|-------|------------|',
245
+ ...data.topTools.map((t) => {
246
+ const pct = total > 0 ? Math.round((t.count / total) * 100) : 0;
247
+ return `| ${t.tool} | ${t.count} | ${pct}% |`;
248
+ }),
249
+ '',
250
+ '## Period Comparison',
251
+ `- **Current**: ${data.periodComparison.current}`,
252
+ `- **Previous**: ${data.periodComparison.previous}`,
253
+ `- **Change**: ${data.periodComparison.changePercent >= 0 ? '+' : ''}${data.periodComparison.changePercent}%`,
254
+ '',
255
+ '## Daily Trend (last 7 days)',
256
+ '| Date | Calls |',
257
+ '|------|-------|',
258
+ ...data.dailyTrend.slice(-7).map((d) => `| ${d.date} | ${d.count} |`),
259
+ ];
260
+ if (input.includeRecommendations) {
261
+ lines.push('', '## Recommendation Accuracy', '_Recommendation tracking requires server-side data. ' +
262
+ 'Use audit_export for full recommendation metrics._');
263
+ }
264
+ return lines.join('\n');
265
+ }
266
+ return stubAnalyticsDashboard(input.period, input.includeRecommendations);
267
+ }
268
+ /**
269
+ * Enterprise usage report handler.
270
+ * Returns comprehensive report with all metrics as markdown (or CSV).
271
+ *
272
+ * Uses real service when db is available, falls back to stub
273
+ */
274
+ export async function executeUsageReport(input, context) {
275
+ const days = periodDays(input.period);
276
+ const svc = resolveAnalyticsService(context);
277
+ if (svc) {
278
+ const data = svc.getUsageReport(days, input.format === 'detailed');
279
+ const { current, previous, changePercent } = data.periodComparison;
280
+ const sign = changePercent >= 0 ? '+' : '';
281
+ if (input.format === 'csv') {
282
+ const csvLines = [
283
+ 'metric,current_period,previous_period,change_percent',
284
+ `total_calls,${current},${previous},${changePercent}`,
285
+ `unique_tools,${data.uniqueTools},,,`,
286
+ ];
287
+ for (const t of data.topTools) {
288
+ csvLines.push(`tool_${t.tool},${t.count},,,`);
289
+ }
290
+ return csvLines.join('\n');
291
+ }
292
+ const lines = [
293
+ `# Enterprise Usage Report (${input.period})`,
294
+ '',
295
+ '## Executive Summary',
296
+ `- **Period**: Last ${days} days`,
297
+ `- **Total tool calls**: ${current} (${sign}${changePercent}% vs previous)`,
298
+ `- **Unique tools**: ${data.uniqueTools}`,
299
+ `- **Data source**: live`,
300
+ '',
301
+ '## Top Tools',
302
+ '| Tool | Calls | % of Total |',
303
+ '|------|-------|------------|',
304
+ ...data.topTools.map((t) => {
305
+ const pct = current > 0 ? Math.round((t.count / current) * 100) : 0;
306
+ return `| ${t.tool} | ${t.count} | ${pct}% |`;
307
+ }),
308
+ '',
309
+ '## Daily Trend',
310
+ '| Date | Calls |',
311
+ '|------|-------|',
312
+ ...data.dailyTrend.slice(-7).map((d) => `| ${d.date} | ${d.count} |`),
313
+ ];
314
+ if (input.format === 'detailed' && data.byActor) {
315
+ lines.push('', '## Per-User Breakdown', '| User | Calls |', '|------|-------|', ...data.byActor.map((a) => `| ${a.actor} | ${a.count} |`));
316
+ }
317
+ return lines.join('\n');
318
+ }
319
+ return stubUsageReport(input.period, input.format);
320
+ }
321
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/tools/analytics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview Real analytics service — queries audit_logs SQLite table
3
+ * @module @skillsmith/mcp-server/tools/analytics.service
4
+ * @see SMI-3916: Wave 2 — Analytics real queries
5
+ *
6
+ * Replaces stub mock data with actual SQL queries against the local
7
+ * audit_logs table. Falls back to the stub when no database is available.
8
+ */
9
+ import type { Database } from '@skillsmith/core';
10
+ export interface AnalyticsData {
11
+ totalToolCalls: number;
12
+ uniqueTools: number;
13
+ topTools: Array<{
14
+ tool: string;
15
+ count: number;
16
+ }>;
17
+ dailyTrend: Array<{
18
+ date: string;
19
+ count: number;
20
+ }>;
21
+ periodComparison: {
22
+ current: number;
23
+ previous: number;
24
+ changePercent: number;
25
+ };
26
+ }
27
+ export interface UsageReportData extends AnalyticsData {
28
+ byActor?: Array<{
29
+ actor: string;
30
+ count: number;
31
+ }>;
32
+ }
33
+ export interface AnalyticsService {
34
+ getDashboardData(periodDays: number): AnalyticsData;
35
+ getUsageReport(periodDays: number, detailed: boolean): UsageReportData;
36
+ }
37
+ /**
38
+ * Create an analytics service backed by real SQLite queries.
39
+ *
40
+ * audit_logs schema columns used:
41
+ * - timestamp (TEXT, ISO-8601) — event time
42
+ * - resource (TEXT) — tool/resource name
43
+ * - actor (TEXT, nullable) — user identifier
44
+ */
45
+ export declare function createRealAnalyticsService(db: Database): AnalyticsService;
46
+ //# sourceMappingURL=analytics.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.service.d.ts","sourceRoot":"","sources":["../../../src/tools/analytics.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAMhD,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChD,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,gBAAgB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/E;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAClD;AAMD,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAA;IACnD,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,eAAe,CAAA;CACvE;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,GAAG,gBAAgB,CAiFzE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @fileoverview Real analytics service — queries audit_logs SQLite table
3
+ * @module @skillsmith/mcp-server/tools/analytics.service
4
+ * @see SMI-3916: Wave 2 — Analytics real queries
5
+ *
6
+ * Replaces stub mock data with actual SQL queries against the local
7
+ * audit_logs table. Falls back to the stub when no database is available.
8
+ */
9
+ /**
10
+ * Create an analytics service backed by real SQLite queries.
11
+ *
12
+ * audit_logs schema columns used:
13
+ * - timestamp (TEXT, ISO-8601) — event time
14
+ * - resource (TEXT) — tool/resource name
15
+ * - actor (TEXT, nullable) — user identifier
16
+ */
17
+ export function createRealAnalyticsService(db) {
18
+ return {
19
+ getDashboardData(periodDays) {
20
+ const since = new Date(Date.now() - periodDays * 86_400_000).toISOString();
21
+ const totalRow = db
22
+ .prepare('SELECT COUNT(*) as count FROM audit_logs WHERE timestamp >= ?')
23
+ .get(since);
24
+ const totalToolCalls = totalRow?.count ?? 0;
25
+ const uniqueRow = db
26
+ .prepare('SELECT COUNT(DISTINCT resource) as count FROM audit_logs WHERE timestamp >= ?')
27
+ .get(since);
28
+ const uniqueTools = uniqueRow?.count ?? 0;
29
+ const topTools = db
30
+ .prepare('SELECT resource as tool, COUNT(*) as count FROM audit_logs ' +
31
+ 'WHERE timestamp >= ? AND resource IS NOT NULL ' +
32
+ 'GROUP BY resource ORDER BY count DESC LIMIT 10')
33
+ .all(since);
34
+ const dailyTrend = db
35
+ .prepare('SELECT DATE(timestamp) as date, COUNT(*) as count FROM audit_logs ' +
36
+ 'WHERE timestamp >= ? GROUP BY DATE(timestamp) ORDER BY date')
37
+ .all(since);
38
+ // Period comparison: current vs previous period of same length
39
+ const previousSince = new Date(Date.now() - periodDays * 2 * 86_400_000).toISOString();
40
+ const previousRow = db
41
+ .prepare('SELECT COUNT(*) as count FROM audit_logs WHERE timestamp >= ? AND timestamp < ?')
42
+ .get(previousSince, since);
43
+ const previous = previousRow?.count ?? 0;
44
+ const changePercent = previous > 0 ? Math.round(((totalToolCalls - previous) / previous) * 100) : 0;
45
+ return {
46
+ totalToolCalls,
47
+ uniqueTools,
48
+ topTools,
49
+ dailyTrend,
50
+ periodComparison: { current: totalToolCalls, previous, changePercent },
51
+ };
52
+ },
53
+ getUsageReport(periodDays, detailed) {
54
+ const data = this.getDashboardData(periodDays);
55
+ if (!detailed) {
56
+ return data;
57
+ }
58
+ // Add per-actor breakdown for detailed mode
59
+ const since = new Date(Date.now() - periodDays * 86_400_000).toISOString();
60
+ const byActor = db
61
+ .prepare('SELECT actor, COUNT(*) as count FROM audit_logs ' +
62
+ 'WHERE timestamp >= ? AND actor IS NOT NULL ' +
63
+ 'GROUP BY actor ORDER BY count DESC LIMIT 20')
64
+ .all(since);
65
+ return { ...data, byActor };
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=analytics.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.service.js","sourceRoot":"","sources":["../../../src/tools/analytics.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6BH;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,EAAY;IACrD,OAAO;QACL,gBAAgB,CAAC,UAAkB;YACjC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;YAE1E,MAAM,QAAQ,GAAG,EAAE;iBAChB,OAAO,CAAoB,+DAA+D,CAAC;iBAC3F,GAAG,CAAC,KAAK,CAAC,CAAA;YACb,MAAM,cAAc,GAAG,QAAQ,EAAE,KAAK,IAAI,CAAC,CAAA;YAE3C,MAAM,SAAS,GAAG,EAAE;iBACjB,OAAO,CAEL,+EAA+E,CAAC;iBAClF,GAAG,CAAC,KAAK,CAAC,CAAA;YACb,MAAM,WAAW,GAAG,SAAS,EAAE,KAAK,IAAI,CAAC,CAAA;YAEzC,MAAM,QAAQ,GAAG,EAAE;iBAChB,OAAO,CAIN,6DAA6D;gBAC3D,gDAAgD;gBAChD,gDAAgD,CACnD;iBACA,GAAG,CAAC,KAAK,CAAC,CAAA;YAEb,MAAM,UAAU,GAAG,EAAE;iBAClB,OAAO,CAIN,oEAAoE;gBAClE,6DAA6D,CAChE;iBACA,GAAG,CAAC,KAAK,CAAC,CAAA;YAEb,+DAA+D;YAC/D,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;YACtF,MAAM,WAAW,GAAG,EAAE;iBACnB,OAAO,CAEL,iFAAiF,CAAC;iBACpF,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAA;YAC5B,MAAM,QAAQ,GAAG,WAAW,EAAE,KAAK,IAAI,CAAC,CAAA;YACxC,MAAM,aAAa,GACjB,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAE/E,OAAO;gBACL,cAAc;gBACd,WAAW;gBACX,QAAQ;gBACR,UAAU;gBACV,gBAAgB,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE;aACvE,CAAA;QACH,CAAC;QAED,cAAc,CAAC,UAAkB,EAAE,QAAiB;YAClD,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAA;YAE9C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,IAAI,CAAA;YACb,CAAC;YAED,4CAA4C;YAC5C,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;YAC1E,MAAM,OAAO,GAAG,EAAE;iBACf,OAAO,CAIN,kDAAkD;gBAChD,6CAA6C;gBAC7C,6CAA6C,CAChD;iBACA,GAAG,CAAC,KAAK,CAAC,CAAA;YAEb,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAA;QAC7B,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Tests for real analytics service (SQLite-backed)
3
+ * @see SMI-3916: Wave 2 — Analytics real queries
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=analytics.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.service.test.d.ts","sourceRoot":"","sources":["../../../src/tools/analytics.service.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @fileoverview Tests for real analytics service (SQLite-backed)
3
+ * @see SMI-3916: Wave 2 — Analytics real queries
4
+ */
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import { createDatabase } from '@skillsmith/core';
7
+ import { createRealAnalyticsService } from './analytics.service.js';
8
+ // ============================================================================
9
+ // Test helpers
10
+ // ============================================================================
11
+ function seedAuditLogs(db, rows) {
12
+ const stmt = db.prepare('INSERT INTO audit_logs (id, event_type, timestamp, actor, resource, action, result) ' +
13
+ 'VALUES (?, ?, ?, ?, ?, ?, ?)');
14
+ for (const row of rows) {
15
+ stmt.run(row.id ?? crypto.randomUUID(), row.event_type ?? 'tool.call', row.timestamp ?? new Date().toISOString(), row.actor ?? null, row.resource ?? null, row.action ?? 'execute', row.result ?? 'success');
16
+ }
17
+ }
18
+ function daysAgo(n) {
19
+ return new Date(Date.now() - n * 86_400_000).toISOString();
20
+ }
21
+ // ============================================================================
22
+ // Tests
23
+ // ============================================================================
24
+ describe('createRealAnalyticsService', () => {
25
+ let db;
26
+ let svc;
27
+ beforeEach(() => {
28
+ db = createDatabase(':memory:');
29
+ svc = createRealAnalyticsService(db);
30
+ });
31
+ afterEach(() => {
32
+ db.close();
33
+ });
34
+ describe('getDashboardData', () => {
35
+ it('returns zero counts for an empty database', () => {
36
+ const data = svc.getDashboardData(30);
37
+ expect(data.totalToolCalls).toBe(0);
38
+ expect(data.uniqueTools).toBe(0);
39
+ expect(data.topTools).toEqual([]);
40
+ expect(data.dailyTrend).toEqual([]);
41
+ expect(data.periodComparison).toEqual({
42
+ current: 0,
43
+ previous: 0,
44
+ changePercent: 0,
45
+ });
46
+ });
47
+ it('counts total tool calls within the period', () => {
48
+ seedAuditLogs(db, [
49
+ { resource: 'search', timestamp: daysAgo(5) },
50
+ { resource: 'search', timestamp: daysAgo(10) },
51
+ { resource: 'install', timestamp: daysAgo(40) }, // outside 30d
52
+ ]);
53
+ const data = svc.getDashboardData(30);
54
+ expect(data.totalToolCalls).toBe(2);
55
+ });
56
+ it('counts unique tools', () => {
57
+ seedAuditLogs(db, [
58
+ { resource: 'search', timestamp: daysAgo(1) },
59
+ { resource: 'search', timestamp: daysAgo(2) },
60
+ { resource: 'install', timestamp: daysAgo(3) },
61
+ { resource: 'validate', timestamp: daysAgo(4) },
62
+ ]);
63
+ const data = svc.getDashboardData(30);
64
+ expect(data.uniqueTools).toBe(3);
65
+ });
66
+ it('returns top tools ordered by count', () => {
67
+ seedAuditLogs(db, [
68
+ { resource: 'search', timestamp: daysAgo(1) },
69
+ { resource: 'search', timestamp: daysAgo(2) },
70
+ { resource: 'search', timestamp: daysAgo(3) },
71
+ { resource: 'install', timestamp: daysAgo(1) },
72
+ { resource: 'install', timestamp: daysAgo(2) },
73
+ { resource: 'validate', timestamp: daysAgo(1) },
74
+ ]);
75
+ const data = svc.getDashboardData(30);
76
+ expect(data.topTools).toHaveLength(3);
77
+ expect(data.topTools[0]).toEqual({ tool: 'search', count: 3 });
78
+ expect(data.topTools[1]).toEqual({ tool: 'install', count: 2 });
79
+ expect(data.topTools[2]).toEqual({ tool: 'validate', count: 1 });
80
+ });
81
+ it('limits top tools to 10', () => {
82
+ const resources = Array.from({ length: 15 }, (_, i) => `tool-${i}`);
83
+ const rows = resources.map((r) => ({ resource: r, timestamp: daysAgo(1) }));
84
+ seedAuditLogs(db, rows);
85
+ const data = svc.getDashboardData(30);
86
+ expect(data.topTools).toHaveLength(10);
87
+ });
88
+ it('produces daily trend grouped by date', () => {
89
+ seedAuditLogs(db, [
90
+ { resource: 'search', timestamp: daysAgo(2) },
91
+ { resource: 'search', timestamp: daysAgo(2) },
92
+ { resource: 'install', timestamp: daysAgo(1) },
93
+ ]);
94
+ const data = svc.getDashboardData(7);
95
+ expect(data.dailyTrend.length).toBeGreaterThanOrEqual(2);
96
+ // Each entry has date + count
97
+ for (const entry of data.dailyTrend) {
98
+ expect(entry.date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
99
+ expect(entry.count).toBeGreaterThanOrEqual(1);
100
+ }
101
+ });
102
+ it('computes period comparison correctly', () => {
103
+ // Previous period: 4 events (60-31 days ago)
104
+ seedAuditLogs(db, [
105
+ { resource: 'a', timestamp: daysAgo(35) },
106
+ { resource: 'a', timestamp: daysAgo(40) },
107
+ { resource: 'a', timestamp: daysAgo(45) },
108
+ { resource: 'a', timestamp: daysAgo(50) },
109
+ ]);
110
+ // Current period: 2 events (within 30 days)
111
+ seedAuditLogs(db, [
112
+ { resource: 'a', timestamp: daysAgo(5) },
113
+ { resource: 'a', timestamp: daysAgo(10) },
114
+ ]);
115
+ const data = svc.getDashboardData(30);
116
+ expect(data.periodComparison.current).toBe(2);
117
+ expect(data.periodComparison.previous).toBe(4);
118
+ expect(data.periodComparison.changePercent).toBe(-50);
119
+ });
120
+ });
121
+ describe('getUsageReport', () => {
122
+ it('returns dashboard data without byActor in non-detailed mode', () => {
123
+ seedAuditLogs(db, [{ resource: 'search', actor: 'alice', timestamp: daysAgo(1) }]);
124
+ const data = svc.getUsageReport(30, false);
125
+ expect(data.totalToolCalls).toBe(1);
126
+ expect(data.byActor).toBeUndefined();
127
+ });
128
+ it('includes byActor in detailed mode', () => {
129
+ seedAuditLogs(db, [
130
+ { resource: 'search', actor: 'alice', timestamp: daysAgo(1) },
131
+ { resource: 'search', actor: 'alice', timestamp: daysAgo(2) },
132
+ { resource: 'install', actor: 'bob', timestamp: daysAgo(1) },
133
+ ]);
134
+ const data = svc.getUsageReport(30, true);
135
+ expect(data.byActor).toBeDefined();
136
+ expect(data.byActor).toHaveLength(2);
137
+ expect(data.byActor[0]).toEqual({ actor: 'alice', count: 2 });
138
+ expect(data.byActor[1]).toEqual({ actor: 'bob', count: 1 });
139
+ });
140
+ it('excludes null actors from byActor', () => {
141
+ seedAuditLogs(db, [
142
+ { resource: 'search', actor: null, timestamp: daysAgo(1) },
143
+ { resource: 'search', actor: 'alice', timestamp: daysAgo(1) },
144
+ ]);
145
+ const data = svc.getUsageReport(30, true);
146
+ expect(data.byActor).toHaveLength(1);
147
+ expect(data.byActor[0].actor).toBe('alice');
148
+ });
149
+ });
150
+ });
151
+ //# sourceMappingURL=analytics.service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.service.test.js","sourceRoot":"","sources":["../../../src/tools/analytics.service.test.ts"],"names":[],"mappings":"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"}