memory-journal-mcp 4.4.2 → 5.0.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 (291) hide show
  1. package/.github/workflows/codeql.yml +1 -6
  2. package/.github/workflows/docker-publish.yml +15 -49
  3. package/.github/workflows/lint-and-test.yml +1 -1
  4. package/.github/workflows/secrets-scanning.yml +4 -3
  5. package/.github/workflows/security-update.yml +3 -3
  6. package/CHANGELOG.md +213 -0
  7. package/CONTRIBUTING.md +132 -97
  8. package/DOCKER_README.md +184 -235
  9. package/Dockerfile +27 -24
  10. package/README.md +218 -190
  11. package/SECURITY.md +27 -35
  12. package/dist/cli.js +16 -1
  13. package/dist/cli.js.map +1 -1
  14. package/dist/constants/ServerInstructions.d.ts +5 -1
  15. package/dist/constants/ServerInstructions.d.ts.map +1 -1
  16. package/dist/constants/ServerInstructions.js +133 -73
  17. package/dist/constants/ServerInstructions.js.map +1 -1
  18. package/dist/constants/icons.d.ts +2 -2
  19. package/dist/constants/icons.d.ts.map +1 -1
  20. package/dist/constants/icons.js +7 -6
  21. package/dist/constants/icons.js.map +1 -1
  22. package/dist/database/SqliteAdapter.d.ts +37 -24
  23. package/dist/database/SqliteAdapter.d.ts.map +1 -1
  24. package/dist/database/SqliteAdapter.js +319 -157
  25. package/dist/database/SqliteAdapter.js.map +1 -1
  26. package/dist/database/schema.d.ts +45 -0
  27. package/dist/database/schema.d.ts.map +1 -0
  28. package/dist/database/schema.js +92 -0
  29. package/dist/database/schema.js.map +1 -0
  30. package/dist/filtering/ToolFilter.d.ts +1 -1
  31. package/dist/filtering/ToolFilter.d.ts.map +1 -1
  32. package/dist/filtering/ToolFilter.js +13 -2
  33. package/dist/filtering/ToolFilter.js.map +1 -1
  34. package/dist/github/GitHubIntegration.d.ts.map +1 -1
  35. package/dist/github/GitHubIntegration.js +1 -3
  36. package/dist/github/GitHubIntegration.js.map +1 -1
  37. package/dist/handlers/prompts/github.d.ts +12 -0
  38. package/dist/handlers/prompts/github.d.ts.map +1 -0
  39. package/dist/handlers/prompts/github.js +178 -0
  40. package/dist/handlers/prompts/github.js.map +1 -0
  41. package/dist/handlers/prompts/index.d.ts +23 -2
  42. package/dist/handlers/prompts/index.d.ts.map +1 -1
  43. package/dist/handlers/prompts/index.js +7 -432
  44. package/dist/handlers/prompts/index.js.map +1 -1
  45. package/dist/handlers/prompts/workflow.d.ts +12 -0
  46. package/dist/handlers/prompts/workflow.d.ts.map +1 -0
  47. package/dist/handlers/prompts/workflow.js +277 -0
  48. package/dist/handlers/prompts/workflow.js.map +1 -0
  49. package/dist/handlers/resources/core.d.ts +11 -0
  50. package/dist/handlers/resources/core.d.ts.map +1 -0
  51. package/dist/handlers/resources/core.js +433 -0
  52. package/dist/handlers/resources/core.js.map +1 -0
  53. package/dist/handlers/resources/github.d.ts +11 -0
  54. package/dist/handlers/resources/github.d.ts.map +1 -0
  55. package/dist/handlers/resources/github.js +314 -0
  56. package/dist/handlers/resources/github.js.map +1 -0
  57. package/dist/handlers/resources/graph.d.ts +11 -0
  58. package/dist/handlers/resources/graph.d.ts.map +1 -0
  59. package/dist/handlers/resources/graph.js +204 -0
  60. package/dist/handlers/resources/graph.js.map +1 -0
  61. package/dist/handlers/resources/index.d.ts +5 -20
  62. package/dist/handlers/resources/index.d.ts.map +1 -1
  63. package/dist/handlers/resources/index.js +16 -1278
  64. package/dist/handlers/resources/index.js.map +1 -1
  65. package/dist/handlers/resources/shared.d.ts +60 -0
  66. package/dist/handlers/resources/shared.d.ts.map +1 -0
  67. package/dist/handlers/resources/shared.js +49 -0
  68. package/dist/handlers/resources/shared.js.map +1 -0
  69. package/dist/handlers/resources/team.d.ts +13 -0
  70. package/dist/handlers/resources/team.d.ts.map +1 -0
  71. package/dist/handlers/resources/team.js +119 -0
  72. package/dist/handlers/resources/team.js.map +1 -0
  73. package/dist/handlers/resources/templates.d.ts +13 -0
  74. package/dist/handlers/resources/templates.d.ts.map +1 -0
  75. package/dist/handlers/resources/templates.js +310 -0
  76. package/dist/handlers/resources/templates.js.map +1 -0
  77. package/dist/handlers/tools/admin.d.ts +8 -0
  78. package/dist/handlers/tools/admin.d.ts.map +1 -0
  79. package/dist/handlers/tools/admin.js +270 -0
  80. package/dist/handlers/tools/admin.js.map +1 -0
  81. package/dist/handlers/tools/analytics.d.ts +8 -0
  82. package/dist/handlers/tools/analytics.d.ts.map +1 -0
  83. package/dist/handlers/tools/analytics.js +256 -0
  84. package/dist/handlers/tools/analytics.js.map +1 -0
  85. package/dist/handlers/tools/backup.d.ts +8 -0
  86. package/dist/handlers/tools/backup.d.ts.map +1 -0
  87. package/dist/handlers/tools/backup.js +224 -0
  88. package/dist/handlers/tools/backup.js.map +1 -0
  89. package/dist/handlers/tools/core.d.ts +9 -0
  90. package/dist/handlers/tools/core.d.ts.map +1 -0
  91. package/dist/handlers/tools/core.js +326 -0
  92. package/dist/handlers/tools/core.js.map +1 -0
  93. package/dist/handlers/tools/export.d.ts +8 -0
  94. package/dist/handlers/tools/export.d.ts.map +1 -0
  95. package/dist/handlers/tools/export.js +89 -0
  96. package/dist/handlers/tools/export.js.map +1 -0
  97. package/dist/handlers/tools/github/helpers.d.ts +34 -0
  98. package/dist/handlers/tools/github/helpers.d.ts.map +1 -0
  99. package/dist/handlers/tools/github/helpers.js +52 -0
  100. package/dist/handlers/tools/github/helpers.js.map +1 -0
  101. package/dist/handlers/tools/github/insights-tools.d.ts +8 -0
  102. package/dist/handlers/tools/github/insights-tools.d.ts.map +1 -0
  103. package/dist/handlers/tools/github/insights-tools.js +104 -0
  104. package/dist/handlers/tools/github/insights-tools.js.map +1 -0
  105. package/dist/handlers/tools/github/issue-tools.d.ts +8 -0
  106. package/dist/handlers/tools/github/issue-tools.d.ts.map +1 -0
  107. package/dist/handlers/tools/github/issue-tools.js +359 -0
  108. package/dist/handlers/tools/github/issue-tools.js.map +1 -0
  109. package/dist/handlers/tools/github/kanban-tools.d.ts +8 -0
  110. package/dist/handlers/tools/github/kanban-tools.d.ts.map +1 -0
  111. package/dist/handlers/tools/github/kanban-tools.js +108 -0
  112. package/dist/handlers/tools/github/kanban-tools.js.map +1 -0
  113. package/dist/handlers/tools/github/milestone-tools.d.ts +9 -0
  114. package/dist/handlers/tools/github/milestone-tools.d.ts.map +1 -0
  115. package/dist/handlers/tools/github/milestone-tools.js +302 -0
  116. package/dist/handlers/tools/github/milestone-tools.js.map +1 -0
  117. package/dist/handlers/tools/github/mutation-tools.d.ts +12 -0
  118. package/dist/handlers/tools/github/mutation-tools.d.ts.map +1 -0
  119. package/dist/handlers/tools/github/mutation-tools.js +15 -0
  120. package/dist/handlers/tools/github/mutation-tools.js.map +1 -0
  121. package/dist/handlers/tools/github/read-tools.d.ts +8 -0
  122. package/dist/handlers/tools/github/read-tools.d.ts.map +1 -0
  123. package/dist/handlers/tools/github/read-tools.js +260 -0
  124. package/dist/handlers/tools/github/read-tools.js.map +1 -0
  125. package/dist/handlers/tools/github/schemas.d.ts +467 -0
  126. package/dist/handlers/tools/github/schemas.d.ts.map +1 -0
  127. package/dist/handlers/tools/github/schemas.js +335 -0
  128. package/dist/handlers/tools/github/schemas.js.map +1 -0
  129. package/dist/handlers/tools/github.d.ts +14 -0
  130. package/dist/handlers/tools/github.d.ts.map +1 -0
  131. package/dist/handlers/tools/github.js +28 -0
  132. package/dist/handlers/tools/github.js.map +1 -0
  133. package/dist/handlers/tools/index.d.ts +15 -20
  134. package/dist/handlers/tools/index.d.ts.map +1 -1
  135. package/dist/handlers/tools/index.js +117 -2909
  136. package/dist/handlers/tools/index.js.map +1 -1
  137. package/dist/handlers/tools/relationships.d.ts +8 -0
  138. package/dist/handlers/tools/relationships.d.ts.map +1 -0
  139. package/dist/handlers/tools/relationships.js +308 -0
  140. package/dist/handlers/tools/relationships.js.map +1 -0
  141. package/dist/handlers/tools/schemas.d.ts +108 -0
  142. package/dist/handlers/tools/schemas.d.ts.map +1 -0
  143. package/dist/handlers/tools/schemas.js +122 -0
  144. package/dist/handlers/tools/schemas.js.map +1 -0
  145. package/dist/handlers/tools/search.d.ts +8 -0
  146. package/dist/handlers/tools/search.d.ts.map +1 -0
  147. package/dist/handlers/tools/search.js +282 -0
  148. package/dist/handlers/tools/search.js.map +1 -0
  149. package/dist/handlers/tools/team.d.ts +11 -0
  150. package/dist/handlers/tools/team.d.ts.map +1 -0
  151. package/dist/handlers/tools/team.js +239 -0
  152. package/dist/handlers/tools/team.js.map +1 -0
  153. package/dist/server/McpServer.d.ts +4 -0
  154. package/dist/server/McpServer.d.ts.map +1 -1
  155. package/dist/server/McpServer.js +48 -297
  156. package/dist/server/McpServer.js.map +1 -1
  157. package/dist/server/Scheduler.d.ts +91 -0
  158. package/dist/server/Scheduler.d.ts.map +1 -0
  159. package/dist/server/Scheduler.js +201 -0
  160. package/dist/server/Scheduler.js.map +1 -0
  161. package/dist/transports/http.d.ts +66 -0
  162. package/dist/transports/http.d.ts.map +1 -0
  163. package/dist/transports/http.js +519 -0
  164. package/dist/transports/http.js.map +1 -0
  165. package/dist/types/entities.d.ts +101 -0
  166. package/dist/types/entities.d.ts.map +1 -0
  167. package/dist/types/entities.js +5 -0
  168. package/dist/types/entities.js.map +1 -0
  169. package/dist/types/filtering.d.ts +34 -0
  170. package/dist/types/filtering.d.ts.map +1 -0
  171. package/dist/types/filtering.js +5 -0
  172. package/dist/types/filtering.js.map +1 -0
  173. package/dist/types/github.d.ts +166 -0
  174. package/dist/types/github.d.ts.map +1 -0
  175. package/dist/types/github.js +5 -0
  176. package/dist/types/github.js.map +1 -0
  177. package/dist/types/index.d.ts +35 -292
  178. package/dist/types/index.d.ts.map +1 -1
  179. package/dist/types/index.js +2 -2
  180. package/dist/types/index.js.map +1 -1
  181. package/dist/utils/error-helpers.d.ts +37 -0
  182. package/dist/utils/error-helpers.d.ts.map +1 -0
  183. package/dist/utils/error-helpers.js +47 -0
  184. package/dist/utils/error-helpers.js.map +1 -0
  185. package/dist/utils/logger.d.ts.map +1 -1
  186. package/dist/utils/logger.js +6 -3
  187. package/dist/utils/logger.js.map +1 -1
  188. package/dist/utils/security-utils.d.ts +0 -21
  189. package/dist/utils/security-utils.d.ts.map +1 -1
  190. package/dist/utils/security-utils.js +0 -47
  191. package/dist/utils/security-utils.js.map +1 -1
  192. package/dist/vector/VectorSearchManager.d.ts.map +1 -1
  193. package/dist/vector/VectorSearchManager.js +9 -32
  194. package/dist/vector/VectorSearchManager.js.map +1 -1
  195. package/docker-compose.yml +11 -2
  196. package/hooks/README.md +107 -0
  197. package/hooks/cursor/hooks.json +10 -0
  198. package/hooks/cursor/memory-journal.mdc +22 -0
  199. package/hooks/cursor/session-end.sh +19 -0
  200. package/hooks/kilo-code/session-end-mode.json +11 -0
  201. package/hooks/kiro/session-end.md +13 -0
  202. package/mcp-config-example.json +1 -0
  203. package/package.json +11 -9
  204. package/playwright.config.ts +29 -0
  205. package/releases/v4.5.0.md +116 -0
  206. package/releases/v5.0.0.md +105 -0
  207. package/scripts/generate-server-instructions.ts +176 -0
  208. package/scripts/server-instructions-function-body.ts +77 -0
  209. package/server.json +3 -3
  210. package/src/cli.ts +45 -1
  211. package/src/constants/ServerInstructions.ts +133 -73
  212. package/src/constants/icons.ts +8 -7
  213. package/src/constants/server-instructions.md +268 -0
  214. package/src/database/SqliteAdapter.ts +358 -192
  215. package/src/database/schema.ts +125 -0
  216. package/src/filtering/ToolFilter.ts +13 -2
  217. package/src/github/GitHubIntegration.ts +1 -3
  218. package/src/handlers/prompts/github.ts +209 -0
  219. package/src/handlers/prompts/index.ts +10 -499
  220. package/src/handlers/prompts/workflow.ts +314 -0
  221. package/src/handlers/resources/core.ts +528 -0
  222. package/src/handlers/resources/github.ts +358 -0
  223. package/src/handlers/resources/graph.ts +254 -0
  224. package/src/handlers/resources/index.ts +23 -1570
  225. package/src/handlers/resources/shared.ts +103 -0
  226. package/src/handlers/resources/team.ts +133 -0
  227. package/src/handlers/resources/templates.ts +374 -0
  228. package/src/handlers/tools/admin.ts +285 -0
  229. package/src/handlers/tools/analytics.ts +301 -0
  230. package/src/handlers/tools/backup.ts +242 -0
  231. package/src/handlers/tools/core.ts +350 -0
  232. package/src/handlers/tools/export.ts +115 -0
  233. package/src/handlers/tools/github/helpers.ts +86 -0
  234. package/src/handlers/tools/github/insights-tools.ts +119 -0
  235. package/src/handlers/tools/github/issue-tools.ts +439 -0
  236. package/src/handlers/tools/github/kanban-tools.ts +134 -0
  237. package/src/handlers/tools/github/milestone-tools.ts +392 -0
  238. package/src/handlers/tools/github/mutation-tools.ts +17 -0
  239. package/src/handlers/tools/github/read-tools.ts +328 -0
  240. package/src/handlers/tools/github/schemas.ts +369 -0
  241. package/src/handlers/tools/github.ts +36 -0
  242. package/src/handlers/tools/index.ts +144 -3325
  243. package/src/handlers/tools/relationships.ts +358 -0
  244. package/src/handlers/tools/schemas.ts +132 -0
  245. package/src/handlers/tools/search.ts +343 -0
  246. package/src/handlers/tools/team.ts +273 -0
  247. package/src/server/McpServer.ts +63 -358
  248. package/src/server/Scheduler.ts +278 -0
  249. package/src/transports/http.ts +635 -0
  250. package/src/types/entities.ts +145 -0
  251. package/src/types/filtering.ts +54 -0
  252. package/src/types/github.ts +180 -0
  253. package/src/types/index.ts +67 -375
  254. package/src/utils/error-helpers.ts +52 -0
  255. package/src/utils/logger.ts +6 -3
  256. package/src/utils/security-utils.ts +0 -52
  257. package/src/vector/VectorSearchManager.ts +9 -33
  258. package/tests/constants/icons.test.ts +1 -2
  259. package/tests/constants/server-instructions.test.ts +30 -4
  260. package/tests/database/sqlite-adapter.test.ts +91 -7
  261. package/tests/e2e/auth.spec.ts +154 -0
  262. package/tests/e2e/health.spec.ts +63 -0
  263. package/tests/e2e/protocols.spec.ts +134 -0
  264. package/tests/e2e/resources.spec.ts +103 -0
  265. package/tests/e2e/scheduler.spec.ts +79 -0
  266. package/tests/e2e/security.spec.ts +91 -0
  267. package/tests/e2e/sessions.spec.ts +95 -0
  268. package/tests/e2e/stateless.spec.ts +121 -0
  269. package/tests/e2e/tools.spec.ts +111 -0
  270. package/tests/filtering/tool-filter.test.ts +46 -0
  271. package/tests/handlers/error-path-coverage.test.ts +324 -0
  272. package/tests/handlers/github-resource-handlers.test.ts +453 -0
  273. package/tests/handlers/github-tool-handlers.test.ts +899 -0
  274. package/tests/handlers/prompt-handler-coverage.test.ts +106 -0
  275. package/tests/handlers/prompt-handlers.test.ts +40 -0
  276. package/tests/handlers/resource-handler-coverage.test.ts +181 -0
  277. package/tests/handlers/resource-handlers.test.ts +33 -9
  278. package/tests/handlers/search-tool-handlers.test.ts +272 -0
  279. package/tests/handlers/targeted-gap-closure.test.ts +387 -0
  280. package/tests/handlers/team-resource-handlers.test.ts +156 -0
  281. package/tests/handlers/team-tool-handlers.test.ts +301 -0
  282. package/tests/handlers/tool-handler-coverage.test.ts +469 -0
  283. package/tests/handlers/tool-handlers.test.ts +2 -2
  284. package/tests/security/sql-injection.test.ts +3 -54
  285. package/tests/server/mcp-server.test.ts +503 -8
  286. package/tests/server/scheduler.test.ts +400 -0
  287. package/tests/transports/http-transport.test.ts +620 -0
  288. package/tests/vector/vector-search-manager.test.ts +60 -0
  289. package/vitest.config.ts +4 -1
  290. package/.memory-journal-team.db +0 -0
  291. package/.vscode/settings.json +0 -84
@@ -0,0 +1,528 @@
1
+ /**
2
+ * Memory Journal MCP Server - Core Resource Definitions
3
+ *
4
+ * Resources: briefing, instructions, recent, significant, tags, statistics, health
5
+ */
6
+
7
+ import type { Tag } from '../../types/index.js'
8
+ import { getAllToolNames } from '../../filtering/ToolFilter.js'
9
+ import { generateInstructions, type InstructionLevel } from '../../constants/ServerInstructions.js'
10
+ import { getPrompts } from '../prompts/index.js'
11
+ import {
12
+ ICON_BRIEFING,
13
+ ICON_CLOCK,
14
+ ICON_HEALTH,
15
+ ICON_STAR,
16
+ ICON_TAG,
17
+ ICON_ANALYTICS,
18
+ } from '../../constants/icons.js'
19
+ import pkg from '../../../package.json' with { type: 'json' }
20
+ import type { InternalResourceDef, ResourceContext, ResourceResult } from './shared.js'
21
+ import { execQuery, transformEntryRow } from './shared.js'
22
+
23
+ /**
24
+ * Get total tool count for health status
25
+ */
26
+ function getTotalToolCount(): number {
27
+ return getAllToolNames().length
28
+ }
29
+
30
+ /**
31
+ * Get core resource definitions
32
+ */
33
+ export function getCoreResourceDefinitions(): InternalResourceDef[] {
34
+ return [
35
+ // Session initialization resource - highest priority
36
+ {
37
+ uri: 'memory://briefing',
38
+ name: 'Initial Briefing',
39
+ title: 'Session Initialization Context',
40
+ description:
41
+ 'AUTO-READ AT SESSION START: Project context for AI agents (~300 tokens). Contains userMessage to show user.',
42
+ mimeType: 'application/json',
43
+ icons: [ICON_BRIEFING],
44
+ annotations: {
45
+ audience: ['assistant'],
46
+ priority: 1.0,
47
+ autoRead: true,
48
+ sessionInit: true,
49
+ },
50
+ handler: async (_uri: string, context: ResourceContext) => {
51
+ // Get latest 3 entries (compact)
52
+ const recentEntries = context.db.getRecentEntries(3)
53
+ const latestEntries = recentEntries.map((e) => ({
54
+ id: e.id,
55
+ timestamp: e.timestamp,
56
+ type: e.entryType,
57
+ preview: e.content.slice(0, 80) + (e.content.length > 80 ? '...' : ''),
58
+ }))
59
+
60
+ // Get compact GitHub status if available
61
+ let github: {
62
+ repo: string | null
63
+ branch: string | null
64
+ ci: 'passing' | 'failing' | 'pending' | 'cancelled' | 'unknown'
65
+ openIssues: number
66
+ openPRs: number
67
+ milestones: { title: string; progress: string; dueOn: string | null }[]
68
+ insights?: {
69
+ stars: number | null
70
+ forks: number | null
71
+ clones14d?: number
72
+ views14d?: number
73
+ }
74
+ } | null = null
75
+
76
+ if (context.github) {
77
+ try {
78
+ const repoInfo = await context.github.getRepoInfo()
79
+ const owner = repoInfo.owner
80
+ const repo = repoInfo.repo
81
+
82
+ if (owner && repo) {
83
+ // Get CI status (based on latest run only)
84
+ let ciStatus:
85
+ | 'passing'
86
+ | 'failing'
87
+ | 'pending'
88
+ | 'cancelled'
89
+ | 'unknown' = 'unknown'
90
+ try {
91
+ const runs = await context.github.getWorkflowRuns(owner, repo, 1)
92
+ if (runs.length > 0) {
93
+ const latestRun = runs[0]
94
+ if (!latestRun) {
95
+ ciStatus = 'unknown'
96
+ } else if (latestRun.status !== 'completed') {
97
+ ciStatus = 'pending'
98
+ } else {
99
+ switch (latestRun.conclusion) {
100
+ case 'success':
101
+ ciStatus = 'passing'
102
+ break
103
+ case 'failure':
104
+ ciStatus = 'failing'
105
+ break
106
+ case 'cancelled':
107
+ ciStatus = 'cancelled'
108
+ break
109
+ default:
110
+ ciStatus = 'unknown'
111
+ }
112
+ }
113
+ }
114
+ } catch {
115
+ // CI status unavailable
116
+ }
117
+
118
+ // Get issue/PR counts
119
+ let openIssues = 0
120
+ let openPRs = 0
121
+ try {
122
+ const issues = await context.github.getIssues(
123
+ owner,
124
+ repo,
125
+ 'open',
126
+ 1
127
+ )
128
+ openIssues = issues.length > 0 ? issues.length : 0
129
+ const prs = await context.github.getPullRequests(
130
+ owner,
131
+ repo,
132
+ 'open',
133
+ 1
134
+ )
135
+ openPRs = prs.length > 0 ? prs.length : 0
136
+ } catch {
137
+ // Counts unavailable
138
+ }
139
+
140
+ // Get milestone summary for briefing
141
+ let milestones: {
142
+ title: string
143
+ progress: string
144
+ dueOn: string | null
145
+ }[] = []
146
+ try {
147
+ const msList = await context.github.getMilestones(
148
+ owner,
149
+ repo,
150
+ 'open',
151
+ 3
152
+ )
153
+ milestones = msList.map((m) => {
154
+ const total = m.closedIssues + m.openIssues
155
+ const pct =
156
+ total > 0 ? Math.round((m.closedIssues / total) * 100) : 0
157
+ return {
158
+ title: m.title,
159
+ progress: `${String(pct)}%`,
160
+ dueOn: m.dueOn,
161
+ }
162
+ })
163
+ } catch {
164
+ // Milestones unavailable
165
+ }
166
+
167
+ // Get repo insights (stars, forks, traffic)
168
+ let insights:
169
+ | {
170
+ stars: number | null
171
+ forks: number | null
172
+ clones14d?: number
173
+ views14d?: number
174
+ }
175
+ | undefined = undefined
176
+ try {
177
+ const repoStats = await context.github.getRepoStats(owner, repo)
178
+ if (repoStats) {
179
+ insights = {
180
+ stars: repoStats.stars ?? null,
181
+ forks: repoStats.forks ?? null,
182
+ }
183
+ // Traffic requires push access - may fail
184
+ try {
185
+ const trafficData = await context.github.getTrafficData(
186
+ owner,
187
+ repo
188
+ )
189
+ if (trafficData) {
190
+ insights.clones14d = trafficData.clones.total
191
+ insights.views14d = trafficData.views.total
192
+ }
193
+ } catch {
194
+ // Traffic data unavailable (requires push access)
195
+ }
196
+ }
197
+ } catch {
198
+ // Repo stats unavailable
199
+ }
200
+
201
+ github = {
202
+ repo: `${owner}/${repo}`,
203
+ branch: repoInfo.branch ?? null,
204
+ ci: ciStatus,
205
+ openIssues,
206
+ openPRs,
207
+ milestones,
208
+ insights,
209
+ }
210
+ }
211
+ } catch {
212
+ // GitHub unavailable
213
+ }
214
+ }
215
+
216
+ // Get entry count for context
217
+ const stats = context.db.getStatistics('week')
218
+ const totalEntries = stats.totalEntries ?? 0
219
+
220
+ // Team DB context (if configured)
221
+ let teamContext:
222
+ | { totalEntries: number; latestPreview: string | null }
223
+ | undefined = undefined
224
+ if (context.teamDb) {
225
+ try {
226
+ const teamStats = context.teamDb.getStatistics('week')
227
+ const teamRecent = context.teamDb.getRecentEntries(1)
228
+ const teamLatest = teamRecent[0]
229
+ ? `#${teamRecent[0].id}: ${teamRecent[0].content.slice(0, 60)}${teamRecent[0].content.length > 60 ? '...' : ''}`
230
+ : null
231
+ teamContext = {
232
+ totalEntries: teamStats.totalEntries ?? 0,
233
+ latestPreview: teamLatest,
234
+ }
235
+ } catch {
236
+ // Team DB unavailable
237
+ }
238
+ }
239
+
240
+ // Determine lastModified from most recent entry or current time
241
+ const lastModified = recentEntries[0]?.timestamp ?? new Date().toISOString()
242
+
243
+ // Build acknowledgment message for user
244
+ const repoName = github?.repo ?? 'local'
245
+ const branchName = github?.branch ?? 'unknown'
246
+ const ciStatus = github?.ci ?? 'unknown'
247
+ const latestPreview = latestEntries[0]
248
+ ? `#${latestEntries[0].id} (${latestEntries[0].type}): ${latestEntries[0].preview}`
249
+ : 'No entries yet'
250
+
251
+ const milestoneRow =
252
+ github?.milestones && github.milestones.length > 0
253
+ ? `\n| **Milestones** | ${github.milestones.map((m) => `${m.title} (${m.progress}${m.dueOn ? `, due ${m.dueOn.split('T')[0] ?? ''}` : ''})`).join(', ')} |`
254
+ : ''
255
+
256
+ // Build insights row for userMessage
257
+ let insightsRow = ''
258
+ if (github?.insights) {
259
+ const parts: string[] = []
260
+ if (github.insights.stars !== null)
261
+ parts.push(`⭐ ${String(github.insights.stars)} stars`)
262
+ if (github.insights.forks !== null)
263
+ parts.push(`🍴 ${String(github.insights.forks)} forks`)
264
+ if (github.insights.clones14d !== undefined)
265
+ parts.push(`📦 ${String(github.insights.clones14d)} clones`)
266
+ if (github.insights.views14d !== undefined)
267
+ parts.push(`👁️ ${String(github.insights.views14d)} views`)
268
+ if (parts.length > 0) {
269
+ const trafficNote = github.insights.clones14d !== undefined ? ' (14d)' : ''
270
+ insightsRow = `\n| **Insights** | ${parts.join(' · ')}${trafficNote} |`
271
+ }
272
+ }
273
+
274
+ return {
275
+ data: {
276
+ version: pkg.version,
277
+ serverTime: new Date().toISOString(),
278
+ journal: {
279
+ totalEntries,
280
+ latestEntries,
281
+ },
282
+ github,
283
+ teamContext,
284
+ behaviors: {
285
+ create: 'implementations, decisions, bug-fixes, milestones',
286
+ search: 'before decisions, referencing prior work',
287
+ link: 'implementation→spec, bugfix→issue',
288
+ },
289
+ templateResources: [
290
+ 'memory://projects/{number}/timeline',
291
+ 'memory://issues/{issue_number}/entries',
292
+ 'memory://prs/{pr_number}/entries',
293
+ 'memory://prs/{pr_number}/timeline',
294
+ 'memory://kanban/{project_number}',
295
+ 'memory://kanban/{project_number}/diagram',
296
+ 'memory://milestones/{number}',
297
+ ],
298
+ more: {
299
+ fullHealth: 'memory://health',
300
+ allRecent: 'memory://recent',
301
+ githubStatus: 'memory://github/status',
302
+ repoInsights: 'memory://github/insights',
303
+ contextBundle: 'get-context-bundle prompt',
304
+ },
305
+ // IMPORTANT: Agent should relay this message to the user
306
+ userMessage: `📋 **Session Context Loaded**
307
+ | Context | Value |
308
+ |---------|-------|
309
+ | **Project** | ${repoName} |
310
+ | **Branch** | ${branchName} |
311
+ | **CI Status** | ${ciStatus} |
312
+ | **Journal** | ${totalEntries} entries |${teamContext ? `\n| **Team DB** | ${teamContext.totalEntries} entries |` : ''}
313
+ | **Latest** | ${latestPreview} |${milestoneRow}${insightsRow}
314
+
315
+ I have project memory access and will create entries for significant work.`,
316
+ // Note for clients that don't auto-inject ServerInstructions
317
+ clientNote:
318
+ 'For complete tool reference and field notes, read memory://instructions.',
319
+ },
320
+ annotations: { lastModified },
321
+ } satisfies ResourceResult
322
+ },
323
+ },
324
+ // Server instructions resource
325
+ {
326
+ uri: 'memory://instructions',
327
+ name: 'Server Instructions',
328
+ title: 'Full Server Behavioral Guidance',
329
+ description: 'Full server instructions for AI agents.',
330
+ mimeType: 'text/markdown',
331
+ icons: [ICON_BRIEFING],
332
+ annotations: {
333
+ audience: ['assistant'],
334
+ priority: 0.95,
335
+ },
336
+ handler: async (_uri: string, context: ResourceContext): Promise<ResourceResult> => {
337
+ const level: InstructionLevel = 'full'
338
+
339
+ const allToolNames = new Set(getAllToolNames())
340
+ const enabledTools = context.filterConfig?.enabledTools ?? allToolNames
341
+
342
+ const prompts = getPrompts().map((p) => {
343
+ const prompt = p as { name: string; description?: string }
344
+ return { name: prompt.name, description: prompt.description }
345
+ })
346
+
347
+ // Deferred import to avoid circular dependency (core → index → core)
348
+ const { getResources } = await import('./index.js')
349
+ const resources = getResources().map((r) => {
350
+ const res = r as { uri: string; name: string; description?: string }
351
+ return { uri: res.uri, name: res.name, description: res.description }
352
+ })
353
+
354
+ const instructions = generateInstructions(
355
+ enabledTools,
356
+ resources,
357
+ prompts,
358
+ undefined,
359
+ level
360
+ )
361
+
362
+ return {
363
+ data: instructions,
364
+ }
365
+ },
366
+ },
367
+ {
368
+ uri: 'memory://recent',
369
+ name: 'Recent Entries',
370
+ title: 'Recent Journal Entries',
371
+ description: '10 most recent journal entries',
372
+ mimeType: 'application/json',
373
+ icons: [ICON_CLOCK],
374
+ annotations: {
375
+ audience: ['assistant'],
376
+ priority: 0.8,
377
+ },
378
+ handler: (_uri: string, context: ResourceContext): ResourceResult => {
379
+ const entries = context.db.getRecentEntries(10)
380
+ const lastModified = entries[0]?.timestamp ?? new Date().toISOString()
381
+ return {
382
+ data: { entries, count: entries.length },
383
+ annotations: { lastModified },
384
+ }
385
+ },
386
+ },
387
+ {
388
+ uri: 'memory://significant',
389
+ name: 'Significant Entries',
390
+ title: 'Significant Milestones',
391
+ description: 'Significant milestones and breakthroughs',
392
+ mimeType: 'application/json',
393
+ icons: [ICON_STAR],
394
+ annotations: {
395
+ audience: ['assistant'],
396
+ priority: 0.7,
397
+ },
398
+ handler: (_uri: string, context: ResourceContext) => {
399
+ const rows = execQuery(
400
+ context.db,
401
+ `
402
+ SELECT * FROM memory_journal
403
+ WHERE significance_type IS NOT NULL
404
+ AND deleted_at IS NULL
405
+ `
406
+ )
407
+ const entriesWithImportance: (Record<string, unknown> & { importance: number })[] =
408
+ rows.map((row) => {
409
+ const entry = transformEntryRow(row)
410
+ const { score: importance } = context.db.calculateImportance(
411
+ entry['id'] as number
412
+ )
413
+ return { ...entry, importance }
414
+ })
415
+ entriesWithImportance.sort((a, b) => {
416
+ if (b.importance !== a.importance) {
417
+ return b.importance - a.importance
418
+ }
419
+ const aTime = new Date(a['timestamp'] as string).getTime()
420
+ const bTime = new Date(b['timestamp'] as string).getTime()
421
+ return bTime - aTime
422
+ })
423
+ const top20 = entriesWithImportance.slice(0, 20)
424
+ return { entries: top20, count: top20.length }
425
+ },
426
+ },
427
+
428
+ {
429
+ uri: 'memory://tags',
430
+ name: 'All Tags',
431
+ title: 'Tag List',
432
+ description: 'All available tags with usage counts',
433
+ mimeType: 'application/json',
434
+ icons: [ICON_TAG],
435
+ annotations: {
436
+ audience: ['assistant'],
437
+ priority: 0.4,
438
+ },
439
+ handler: (_uri: string, context: ResourceContext) => {
440
+ const tags: Tag[] = context.db.listTags()
441
+ const mappedTags = tags.map((t) => ({
442
+ id: t.id,
443
+ name: t.name,
444
+ count: t.usageCount,
445
+ }))
446
+ return { tags: mappedTags, count: mappedTags.length }
447
+ },
448
+ },
449
+ {
450
+ uri: 'memory://statistics',
451
+ name: 'Statistics',
452
+ title: 'Journal Statistics',
453
+ description: 'Overall journal statistics',
454
+ mimeType: 'application/json',
455
+ icons: [ICON_ANALYTICS],
456
+ annotations: {
457
+ audience: ['assistant'],
458
+ priority: 0.4,
459
+ },
460
+ handler: (_uri: string, context: ResourceContext) => {
461
+ return context.db.getStatistics('week')
462
+ },
463
+ },
464
+ {
465
+ uri: 'memory://health',
466
+ name: 'Server Health',
467
+ title: 'Server Health & Diagnostics',
468
+ description:
469
+ 'Server health status including database, backups, vector index (real-time stats), and tool filter status',
470
+ mimeType: 'application/json',
471
+ icons: [ICON_HEALTH],
472
+ annotations: {
473
+ audience: ['assistant'],
474
+ priority: 0.9,
475
+ },
476
+ handler: async (_uri: string, context: ResourceContext): Promise<ResourceResult> => {
477
+ const dbHealth = context.db.getHealthStatus()
478
+
479
+ let vectorIndex: {
480
+ available: boolean
481
+ itemCount: number
482
+ modelName: string | null
483
+ } | null = null
484
+ if (context.vectorManager) {
485
+ try {
486
+ const stats = await context.vectorManager.getStats()
487
+ vectorIndex = {
488
+ available: true,
489
+ itemCount: stats.itemCount,
490
+ modelName: stats.modelName,
491
+ }
492
+ } catch {
493
+ vectorIndex = { available: false, itemCount: 0, modelName: null }
494
+ }
495
+ }
496
+
497
+ const totalTools = getTotalToolCount()
498
+ const toolFilter = {
499
+ active: context.filterConfig !== null && context.filterConfig !== undefined,
500
+ enabledCount: context.filterConfig?.enabledTools.size ?? totalTools,
501
+ totalCount: totalTools,
502
+ filterString: context.filterConfig?.raw ?? null,
503
+ }
504
+
505
+ const lastModified = new Date().toISOString()
506
+
507
+ return {
508
+ data: {
509
+ ...dbHealth,
510
+ vectorIndex,
511
+ toolFilter,
512
+ teamDatabase: context.teamDb
513
+ ? {
514
+ configured: true,
515
+ ...context.teamDb.getHealthStatus(),
516
+ }
517
+ : { configured: false },
518
+ scheduler: context.scheduler
519
+ ? context.scheduler.getStatus()
520
+ : { active: false, jobs: [] },
521
+ timestamp: lastModified,
522
+ },
523
+ annotations: { lastModified },
524
+ }
525
+ },
526
+ },
527
+ ]
528
+ }