hippocamp 0.1.1 → 0.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.
@@ -6,6 +6,13 @@ const nodePath = require("node:path");
6
6
  const { z } = require("zod");
7
7
  const memory = require("./hippocamp-memory.cjs");
8
8
 
9
+ const projectRootSchema = z
10
+ .string()
11
+ .optional()
12
+ .refine((value) => !value || memory.isProjectRepository(value), {
13
+ message: "projectRoot must be an existing directory inside a Git repository. Omit it to use the current project.",
14
+ });
15
+
9
16
  function toTextResult(payload) {
10
17
  return {
11
18
  content: [
@@ -25,6 +32,8 @@ Runs a local stdio MCP server for Hippocamp memory.
25
32
  Environment:
26
33
  HIPPOCAMP_GLOBAL_ROOT Local path to the Lagoon clone. Default: ~/.lagoon
27
34
  HIPPOCAMP_PROJECT_ROOT Project root used to infer the current project slug. Default: current working directory
35
+ HIPPOCAMP_AGENT Optional agent label for event provenance. Usually set by installers.
36
+ HIPPOCAMP_SESSION Optional session id. Defaults to a process-lifetime mcp-XXXXXXXX id.
28
37
 
29
38
  Tools:
30
39
  wake_up
@@ -64,7 +73,7 @@ async function main() {
64
73
  description:
65
74
  "Load the default global and project wake-up files. Use this at the start of a top-level task thread.",
66
75
  inputSchema: {
67
- projectRoot: z.string().optional(),
76
+ projectRoot: projectRootSchema,
68
77
  },
69
78
  },
70
79
  async ({ projectRoot }) => toTextResult(await memory.wakeUp({ projectRoot })),
@@ -77,7 +86,7 @@ async function main() {
77
86
  inputSchema: {
78
87
  scope: z.enum(["global", "project"]),
79
88
  path: z.string(),
80
- projectRoot: z.string().optional(),
89
+ projectRoot: projectRootSchema,
81
90
  },
82
91
  },
83
92
  async ({ scope, path, projectRoot }) =>
@@ -88,13 +97,13 @@ async function main() {
88
97
  "write_memory_file",
89
98
  {
90
99
  description:
91
- "Create or overwrite one memory file. Use this for curated files like identity.md, current_state.md, or open_threads.md.",
100
+ "Create or overwrite one memory file. Use this for curated files like identity.md, current_state.md, or open_threads.md. Paths under events/ are rejected; use append_event.",
92
101
  inputSchema: {
93
102
  scope: z.enum(["global", "project"]),
94
103
  path: z.string(),
95
104
  content: z.string(),
96
105
  sync: z.boolean().optional(),
97
- projectRoot: z.string().optional(),
106
+ projectRoot: projectRootSchema,
98
107
  },
99
108
  },
100
109
  async ({ scope, path, content, sync, projectRoot }) =>
@@ -105,18 +114,30 @@ async function main() {
105
114
  "append_event",
106
115
  {
107
116
  description:
108
- "Append a dated event entry under events/YYYY-MM-DD.md and update the sibling cue index. Store references to GitHub artifacts instead of copying their content.",
117
+ "Append a dated event entry under events/YYYY-MM-DD.md and update the sibling cue index. Requires a title and 1-8 short cues for recall. Automatically stamps Agent/Session provenance when available. Store references to GitHub artifacts instead of copying their content.",
109
118
  inputSchema: {
110
119
  scope: z.enum(["global", "project"]).default("project"),
111
- title: z.string().optional(),
112
- cues: z.array(z.string()).optional(),
120
+ title: z.string().trim().min(1),
121
+ cues: z.array(z.string().trim().min(1)).min(1).max(8),
113
122
  content: z.string(),
114
123
  sync: z.boolean().optional(),
115
- projectRoot: z.string().optional(),
124
+ projectRoot: projectRootSchema,
116
125
  },
117
126
  },
118
- async ({ scope, title, cues, content, sync, projectRoot }) =>
119
- toTextResult(await memory.appendEvent({ scope, title, cues, content, projectRoot, sync })),
127
+ async ({ scope, title, cues, content, sync, projectRoot }) => {
128
+ const clientVersion = server.server?.getClientVersion?.();
129
+ return toTextResult(
130
+ await memory.appendEvent({
131
+ scope,
132
+ title,
133
+ cues,
134
+ content,
135
+ projectRoot,
136
+ sync,
137
+ clientName: clientVersion?.name,
138
+ }),
139
+ );
140
+ },
120
141
  );
121
142
 
122
143
  server.registerTool(
@@ -126,7 +147,7 @@ async function main() {
126
147
  inputSchema: {
127
148
  scope: z.enum(["global", "project"]),
128
149
  path: z.string().optional(),
129
- projectRoot: z.string().optional(),
150
+ projectRoot: projectRootSchema,
130
151
  },
131
152
  },
132
153
  async ({ scope, path, projectRoot }) =>
@@ -141,12 +162,12 @@ async function main() {
141
162
  "search_memory",
142
163
  {
143
164
  description:
144
- "Fuzzy-search memory files. Event search ranks indexed cues and headings first. Use this only when the wake-up files are insufficient, not as the default startup path.",
165
+ "Search task-specific memory. Event search uses cue indexes and returns only bounded coherent evidence; it does not scan unindexed event logs as a fallback.",
145
166
  inputSchema: {
146
167
  query: z.string(),
147
168
  scope: z.enum(["global", "project", "both"]).default("both"),
148
169
  maxResults: z.number().int().min(1).max(20).optional(),
149
- projectRoot: z.string().optional(),
170
+ projectRoot: projectRootSchema,
150
171
  },
151
172
  },
152
173
  async ({ query, scope, maxResults, projectRoot }) =>
@@ -161,7 +182,7 @@ async function main() {
161
182
  inputSchema: {
162
183
  scope: z.enum(["global", "project"]),
163
184
  path: z.string().optional(),
164
- projectRoot: z.string().optional(),
185
+ projectRoot: projectRootSchema,
165
186
  message: z.string().optional(),
166
187
  },
167
188
  },