@gmickel/gno 1.40.0 → 1.42.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 (62) hide show
  1. package/README.md +1 -0
  2. package/assets/skill/SKILL.md +22 -1
  3. package/assets/skill/cli-reference.md +48 -0
  4. package/assets/skill/mcp-reference.md +31 -0
  5. package/browser-extension/artifacts/{gno-browser-clipper-v1.40.0.zip → gno-browser-clipper-v1.42.0.zip} +0 -0
  6. package/browser-extension/artifacts/gno-browser-clipper-v1.42.0.zip.sha256 +1 -0
  7. package/browser-extension/dist/manifest.json +1 -1
  8. package/package.json +3 -2
  9. package/spec/cli.md +146 -7
  10. package/spec/db/schema.sql +17 -0
  11. package/spec/mcp.md +350 -6
  12. package/spec/output-schemas/memory-recall.schema.json +159 -0
  13. package/spec/output-schemas/memory-remember.schema.json +164 -0
  14. package/spec/output-schemas/status.schema.json +269 -54
  15. package/src/cli/commands/daemon.ts +1 -0
  16. package/src/cli/commands/mcp.ts +3 -1
  17. package/src/cli/commands/memory.ts +491 -0
  18. package/src/cli/commands/status.ts +23 -4
  19. package/src/cli/options.ts +4 -0
  20. package/src/cli/program.ts +155 -0
  21. package/src/config/types.ts +10 -0
  22. package/src/core/audit-provenance.ts +91 -0
  23. package/src/core/audit-workspace.ts +17 -0
  24. package/src/core/connector-verifier.ts +2 -4
  25. package/src/core/memory-diagnostics.ts +144 -0
  26. package/src/core/memory-fence.ts +239 -0
  27. package/src/core/memory-recall.ts +269 -0
  28. package/src/core/memory-record.ts +435 -0
  29. package/src/core/memory-remember.ts +425 -0
  30. package/src/core/memory-types.ts +211 -0
  31. package/src/core/memory.ts +87 -0
  32. package/src/ingestion/sync.ts +17 -0
  33. package/src/mcp/AGENTS.md +7 -1
  34. package/src/mcp/CLAUDE.md +7 -1
  35. package/src/mcp/context.ts +37 -7
  36. package/src/mcp/http-egress.ts +2 -0
  37. package/src/mcp/http-modern.ts +214 -0
  38. package/src/mcp/http-security.ts +5 -0
  39. package/src/mcp/http-session.ts +4 -3
  40. package/src/mcp/http-transport.ts +81 -12
  41. package/src/mcp/resources/index.ts +3 -6
  42. package/src/mcp/server.ts +18 -16
  43. package/src/mcp/stdio-serving.ts +45 -0
  44. package/src/mcp/tool-descriptions-core.ts +56 -0
  45. package/src/mcp/tool-profile.ts +112 -0
  46. package/src/mcp/tools/index.ts +286 -126
  47. package/src/mcp/tools/memory-recall.ts +122 -0
  48. package/src/mcp/tools/memory-remember.ts +177 -0
  49. package/src/mcp/tools/memory-shared.ts +86 -0
  50. package/src/pipeline/search.ts +2 -0
  51. package/src/pipeline/types.ts +8 -0
  52. package/src/sdk/client.ts +94 -1
  53. package/src/sdk/index.ts +13 -0
  54. package/src/sdk/types.ts +28 -0
  55. package/src/serve/routes/api.ts +167 -0
  56. package/src/serve/routes/mcp.ts +1 -0
  57. package/src/serve/server.ts +27 -0
  58. package/src/store/migrations/027-memory-scopes.ts +37 -0
  59. package/src/store/migrations/index.ts +2 -0
  60. package/src/store/sqlite/adapter.ts +127 -3
  61. package/src/store/types.ts +54 -0
  62. package/browser-extension/artifacts/gno-browser-clipper-v1.40.0.zip.sha256 +0 -1
@@ -4,7 +4,7 @@
4
4
  * @module src/mcp/tools
5
5
  */
6
6
 
7
- import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import type { McpServer } from "@modelcontextprotocol/server";
8
8
 
9
9
  import { z } from "zod";
10
10
 
@@ -18,6 +18,11 @@ import { CAPTURE_MAX_TEXT_BYTES } from "../../core/capture";
18
18
  import { NOTE_PRESETS, type NotePresetId } from "../../core/note-presets";
19
19
  import { RETRIEVAL_TRACE_METADATA } from "../../core/retrieval-trace-session";
20
20
  import { normalizeTag } from "../../core/tags";
21
+ import { profileToolDescription } from "../tool-descriptions-core";
22
+ import {
23
+ createProfileToolRegistrar,
24
+ DEFAULT_MCP_TOOL_PROFILE,
25
+ } from "../tool-profile";
21
26
  import { handleAddCollection } from "./add-collection";
22
27
  import { askInputSchema, handleAsk } from "./ask";
23
28
  import { AUDIT_MCP_ANNOTATIONS, auditInputSchema, handleAudit } from "./audit";
@@ -64,6 +69,16 @@ import {
64
69
  } from "./links";
65
70
  import { handleListJobs } from "./list-jobs";
66
71
  import { handleListTags } from "./list-tags";
72
+ import {
73
+ handleRecall,
74
+ RECALL_MCP_ANNOTATIONS,
75
+ recallInputSchema,
76
+ } from "./memory-recall";
77
+ import {
78
+ handleRemember,
79
+ REMEMBER_MCP_ANNOTATIONS,
80
+ rememberInputSchema,
81
+ } from "./memory-remember";
67
82
  import { handleMultiGet } from "./multi-get";
68
83
  import { handlePeek, PEEK_MCP_ANNOTATIONS } from "./peek";
69
84
  import { handleQuery, handleQueryDiagnose } from "./query";
@@ -140,11 +155,16 @@ export const MCP_TOOL_DESCRIPTIONS = {
140
155
  contextVerify:
141
156
  "Verify a saved Context Capsule without rebuilding or mutating it. Reports unchanged, stale, missing, reranked, and fingerprint drift states against the active index.",
142
157
  ask: "Generate one answer from a deterministic Context Capsule, verify every substantive claim against exact retained spans, and abstain unless support coverage is complete. Read-only; returns the Capsule, freshness receipt, claim verdicts, gaps, and evidence IDs.",
158
+ recall:
159
+ "Recall current facts from a memory-managed collection for explicit scopes. Call before answering about the user's preferences, decisions, people, or prior work, and before gno_remember to find the predecessor of a changed fact. Returns at most 8 facts within 512 tokens by default, each with text, scopes, provenance, gno:// cite, and content hash, plus a content-free receipt; superseded facts are excluded. Pass the receipt to gno_remember when a stored fact derives from this recall. An empty result names the command that stores the first fact.",
160
+ remember:
161
+ "Store one fact in a memory-managed collection under explicit scopes. Call when the user states a durable preference, decision, or fact worth recalling later; use gno_capture for documents and file edits for existing notes. Without decision it returns likely matches and writes nothing; decision=add writes a new fact; decision=supersede replaces predecessorUri after a hash check, one successor per fact. Exact duplicates return the existing record. Text that replays a recall receipt span or declares a gno:// origin is rejected. The fact is lexically searchable when the call returns.",
143
162
  } as const;
144
163
 
145
164
  /** Tool names whose execution mutates disk, config, or index state. */
146
165
  export const MCP_WRITE_TOOL_NAMES = new Set([
147
166
  "gno_capture",
167
+ "gno_remember",
148
168
  "gno_add_collection",
149
169
  "gno_sync",
150
170
  "gno_embed",
@@ -1012,16 +1032,22 @@ function parseErrorMessage(message: string): { [x: string]: unknown } {
1012
1032
 
1013
1033
  export function registerTools(server: McpServer, ctx: ToolContext): void {
1014
1034
  // Tool IDs use underscores (MCP pattern: ^[a-zA-Z0-9_-]{1,64}$)
1015
- server.registerTool(
1035
+ const profile = ctx.toolProfile ?? DEFAULT_MCP_TOOL_PROFILE;
1036
+ const registerTool = createProfileToolRegistrar(server, profile);
1037
+ // The core profile serves micro-instruction variants; full keeps the
1038
+ // original strings verbatim (legacy golden + tool-profile byte-compat).
1039
+ const describe = (name: string, fullDescription: string) =>
1040
+ profileToolDescription(profile, name, fullDescription);
1041
+ registerTool(
1016
1042
  "gno_context",
1017
1043
  {
1018
- description: MCP_TOOL_DESCRIPTIONS.context,
1044
+ description: describe("gno_context", MCP_TOOL_DESCRIPTIONS.context),
1019
1045
  inputSchema: contextBuildSurfaceSchema,
1020
1046
  },
1021
1047
  (args) => handleContext(args, ctx)
1022
1048
  );
1023
1049
 
1024
- server.registerTool(
1050
+ registerTool(
1025
1051
  "gno_context_verify",
1026
1052
  {
1027
1053
  description: MCP_TOOL_DESCRIPTIONS.contextVerify,
@@ -1030,49 +1056,78 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1030
1056
  (args) => handleContextVerify(args, ctx)
1031
1057
  );
1032
1058
 
1033
- server.tool(
1059
+ registerTool(
1034
1060
  "gno_ask",
1035
- MCP_TOOL_DESCRIPTIONS.ask,
1036
- askInputSchema.shape,
1061
+ {
1062
+ description: MCP_TOOL_DESCRIPTIONS.ask,
1063
+ // The advertised 2025-11-25 schema is the non-strict shape (SDK v1
1064
+ // registered `.shape`); the handler still parses with the strict schema.
1065
+ inputSchema: z.object(askInputSchema.shape),
1066
+ },
1037
1067
  (args) => handleAsk(args, ctx)
1038
1068
  );
1039
1069
 
1040
- server.tool(
1070
+ registerTool(
1071
+ "gno_recall",
1072
+ {
1073
+ description: describe("gno_recall", MCP_TOOL_DESCRIPTIONS.recall),
1074
+ inputSchema: recallInputSchema,
1075
+ annotations: RECALL_MCP_ANNOTATIONS,
1076
+ },
1077
+ (args, request) =>
1078
+ handleRecall(args, ctx, {
1079
+ clientName: server.server.getClientVersion()?.name,
1080
+ sessionId: request.sessionId,
1081
+ requestIdentity: ctx.getRequestIdentity?.(),
1082
+ })
1083
+ );
1084
+
1085
+ registerTool(
1041
1086
  "gno_search",
1042
- MCP_TOOL_DESCRIPTIONS.search,
1043
- searchInputSchema.shape,
1087
+ {
1088
+ description: describe("gno_search", MCP_TOOL_DESCRIPTIONS.search),
1089
+ inputSchema: searchInputSchema,
1090
+ },
1044
1091
  (args) => handleSearch(args, ctx)
1045
1092
  );
1046
1093
 
1047
- server.tool(
1094
+ registerTool(
1048
1095
  "gno_vsearch",
1049
- MCP_TOOL_DESCRIPTIONS.vsearch,
1050
- vsearchInputSchema.shape,
1096
+ {
1097
+ description: MCP_TOOL_DESCRIPTIONS.vsearch,
1098
+ inputSchema: vsearchInputSchema,
1099
+ },
1051
1100
  (args) => handleVsearch(args, ctx)
1052
1101
  );
1053
1102
 
1054
- server.tool(
1103
+ registerTool(
1055
1104
  "gno_query",
1056
- MCP_TOOL_DESCRIPTIONS.query,
1057
- queryInputSchema.shape,
1105
+ {
1106
+ description: describe("gno_query", MCP_TOOL_DESCRIPTIONS.query),
1107
+ inputSchema: queryInputSchema,
1108
+ },
1058
1109
  (args) => handleQuery(args, ctx)
1059
1110
  );
1060
1111
 
1061
- server.tool(
1112
+ registerTool(
1062
1113
  "gno_query_diagnose",
1063
- MCP_TOOL_DESCRIPTIONS.queryDiagnose,
1064
- queryDiagnoseInputSchema.shape,
1114
+ {
1115
+ description: MCP_TOOL_DESCRIPTIONS.queryDiagnose,
1116
+ inputSchema: queryDiagnoseInputSchema,
1117
+ },
1065
1118
  (args) => handleQueryDiagnose(args, ctx)
1066
1119
  );
1067
1120
 
1068
- server.tool(
1121
+ registerTool(
1069
1122
  "gno_get",
1070
- MCP_TOOL_DESCRIPTIONS.get,
1071
- getInputSchema.shape,
1123
+ {
1124
+ description: describe("gno_get", MCP_TOOL_DESCRIPTIONS.get),
1125
+ inputSchema: getInputSchema,
1126
+ },
1072
1127
  (args) => handleGet(args, ctx)
1073
1128
  );
1074
1129
 
1075
- server.registerTool(
1130
+ registerTool(
1076
1131
  "gno_section",
1077
1132
  {
1078
1133
  description: MCP_TOOL_DESCRIPTIONS.section,
@@ -1083,14 +1138,16 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1083
1138
  (args) => handleSection(args, ctx)
1084
1139
  );
1085
1140
 
1086
- server.tool(
1141
+ registerTool(
1087
1142
  "gno_multi_get",
1088
- MCP_TOOL_DESCRIPTIONS.multiGet,
1089
- multiGetInputSchema.shape,
1143
+ {
1144
+ description: describe("gno_multi_get", MCP_TOOL_DESCRIPTIONS.multiGet),
1145
+ inputSchema: multiGetInputSchema,
1146
+ },
1090
1147
  (args) => handleMultiGet(args, ctx)
1091
1148
  );
1092
1149
 
1093
- server.registerTool(
1150
+ registerTool(
1094
1151
  "gno_peek",
1095
1152
  {
1096
1153
  description: MCP_TOOL_DESCRIPTIONS.peek,
@@ -1100,24 +1157,26 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1100
1157
  (args) => handlePeek(args, ctx)
1101
1158
  );
1102
1159
 
1103
- server.tool(
1160
+ registerTool(
1104
1161
  "gno_status",
1105
- MCP_TOOL_DESCRIPTIONS.status,
1106
- statusInputSchema.shape,
1162
+ {
1163
+ description: MCP_TOOL_DESCRIPTIONS.status,
1164
+ inputSchema: statusInputSchema,
1165
+ },
1107
1166
  (args) => handleStatus(args, ctx)
1108
1167
  );
1109
1168
 
1110
- server.registerTool(
1169
+ registerTool(
1111
1170
  "gno_audit",
1112
1171
  {
1113
1172
  description: MCP_TOOL_DESCRIPTIONS.audit,
1114
1173
  inputSchema: auditInputSchema,
1115
1174
  annotations: AUDIT_MCP_ANNOTATIONS,
1116
1175
  },
1117
- (args, extra) => handleAudit(args, ctx, extra.signal)
1176
+ (args, request) => handleAudit(args, ctx, request.mcpReq.signal)
1118
1177
  );
1119
1178
 
1120
- server.registerTool(
1179
+ registerTool(
1121
1180
  "gno_egress_policy_get",
1122
1181
  {
1123
1182
  description:
@@ -1127,7 +1186,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1127
1186
  (args) => handleEgressPolicyGet(args, ctx)
1128
1187
  );
1129
1188
 
1130
- server.registerTool(
1189
+ registerTool(
1131
1190
  "gno_egress_check",
1132
1191
  {
1133
1192
  description:
@@ -1137,7 +1196,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1137
1196
  (args) => handleEgressCheck(args, ctx)
1138
1197
  );
1139
1198
 
1140
- server.registerTool(
1199
+ registerTool(
1141
1200
  "gno_egress_audit_list",
1142
1201
  {
1143
1202
  description:
@@ -1147,7 +1206,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1147
1206
  (args) => handleEgressAuditList(args, ctx)
1148
1207
  );
1149
1208
 
1150
- server.registerTool(
1209
+ registerTool(
1151
1210
  "gno_egress_audit_show",
1152
1211
  {
1153
1212
  description: "Inspect one content-free local egress decision receipt.",
@@ -1156,7 +1215,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1156
1215
  (args) => handleEgressAuditShow(args, ctx)
1157
1216
  );
1158
1217
 
1159
- server.registerTool(
1218
+ registerTool(
1160
1219
  "gno_egress_audit_status",
1161
1220
  {
1162
1221
  description: "Show local egress audit retention and storage status.",
@@ -1165,99 +1224,140 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1165
1224
  (args) => handleEgressAuditStatus(args, ctx)
1166
1225
  );
1167
1226
 
1168
- server.tool(
1227
+ registerTool(
1169
1228
  "gno_changes",
1170
- "List retained metadata-only document changes with opaque cursor pagination and retention disclosure.",
1171
- changesInputSchema.shape,
1229
+ {
1230
+ description: describe(
1231
+ "gno_changes",
1232
+ "List retained metadata-only document changes with opaque cursor pagination and retention disclosure."
1233
+ ),
1234
+ inputSchema: changesInputSchema,
1235
+ },
1172
1236
  (args) => handleChanges(args, ctx)
1173
1237
  );
1174
1238
 
1175
- server.tool(
1239
+ registerTool(
1176
1240
  "gno_diff",
1177
- "Inspect one retained metadata-only structural document change. Source bodies are never returned.",
1178
- diffInputSchema.shape,
1241
+ {
1242
+ description:
1243
+ "Inspect one retained metadata-only structural document change. Source bodies are never returned.",
1244
+ inputSchema: diffInputSchema,
1245
+ },
1179
1246
  (args) => handleDiff(args, ctx)
1180
1247
  );
1181
1248
 
1182
- server.tool(
1249
+ registerTool(
1183
1250
  "gno_impact",
1184
- "Find bounded inbound typed, wiki, and Markdown dependencies with deterministic evidence paths.",
1185
- impactInputSchema.shape,
1251
+ {
1252
+ description:
1253
+ "Find bounded inbound typed, wiki, and Markdown dependencies with deterministic evidence paths.",
1254
+ inputSchema: impactInputSchema,
1255
+ },
1186
1256
  (args) => handleImpact(args, ctx)
1187
1257
  );
1188
1258
 
1189
- server.tool(
1259
+ registerTool(
1190
1260
  "gno_trace_list",
1191
- "List bounded metadata-only summaries of private local retrieval traces. Raw replay queries are omitted from history.",
1192
- traceListInputSchema.shape,
1261
+ {
1262
+ description:
1263
+ "List bounded metadata-only summaries of private local retrieval traces. Raw replay queries are omitted from history.",
1264
+ inputSchema: traceListInputSchema,
1265
+ },
1193
1266
  (args) => handleTraceList(args, ctx)
1194
1267
  );
1195
1268
 
1196
- server.tool(
1269
+ registerTool(
1197
1270
  "gno_trace_show",
1198
- "Inspect one bounded local retrieval trace. Replay-mode content is returned only for the explicitly requested trace.",
1199
- traceShowInputSchema.shape,
1271
+ {
1272
+ description:
1273
+ "Inspect one bounded local retrieval trace. Replay-mode content is returned only for the explicitly requested trace.",
1274
+ inputSchema: traceShowInputSchema,
1275
+ },
1200
1276
  (args) => handleTraceShow(args, ctx)
1201
1277
  );
1202
1278
 
1203
- server.tool(
1279
+ registerTool(
1204
1280
  "gno_list_tags",
1205
- "List all tags with document counts. Use prefix to filter hierarchical tags (e.g. 'project/').",
1206
- listTagsInputSchema.shape,
1281
+ {
1282
+ description:
1283
+ "List all tags with document counts. Use prefix to filter hierarchical tags (e.g. 'project/').",
1284
+ inputSchema: listTagsInputSchema,
1285
+ },
1207
1286
  (args) => handleListTags(args, ctx)
1208
1287
  );
1209
1288
 
1210
- server.tool(
1289
+ registerTool(
1211
1290
  "gno_links",
1212
- "Get outgoing wiki ([[links]]) and markdown links from one document. Use after gno_query when you need immediate local expansion from a known source document; use gno_graph_neighbors for bidirectional graph navigation.",
1213
- linksInputSchema.shape,
1291
+ {
1292
+ description:
1293
+ "Get outgoing wiki ([[links]]) and markdown links from one document. Use after gno_query when you need immediate local expansion from a known source document; use gno_graph_neighbors for bidirectional graph navigation.",
1294
+ inputSchema: linksInputSchema,
1295
+ },
1214
1296
  (args) => handleLinks(args, ctx)
1215
1297
  );
1216
1298
 
1217
- server.tool(
1299
+ registerTool(
1218
1300
  "gno_backlinks",
1219
- "Find all documents that link TO a given document. Use after gno_query/gno_get to discover incoming references around a known target; use gno_graph_path for 'how are X and Y connected?' questions.",
1220
- backlinksInputSchema.shape,
1301
+ {
1302
+ description:
1303
+ "Find all documents that link TO a given document. Use after gno_query/gno_get to discover incoming references around a known target; use gno_graph_path for 'how are X and Y connected?' questions.",
1304
+ inputSchema: backlinksInputSchema,
1305
+ },
1221
1306
  (args) => handleBacklinks(args, ctx)
1222
1307
  );
1223
1308
 
1224
- server.tool(
1309
+ registerTool(
1225
1310
  "gno_similar",
1226
- "Find semantically similar documents using vector embeddings. Use for local expansion when wording differs; use gno_query as the default retrieval entry point and gno_graph_neighbors/path for explicit relationship questions.",
1227
- similarInputSchema.shape,
1311
+ {
1312
+ description:
1313
+ "Find semantically similar documents using vector embeddings. Use for local expansion when wording differs; use gno_query as the default retrieval entry point and gno_graph_neighbors/path for explicit relationship questions.",
1314
+ inputSchema: similarInputSchema,
1315
+ },
1228
1316
  (args) => handleSimilar(args, ctx)
1229
1317
  );
1230
1318
 
1231
- server.tool(
1319
+ registerTool(
1232
1320
  "gno_graph",
1233
- "Get graph report/stats plus nodes/edges for corpus navigation. Use for unfamiliar corpus structure, hubs/isolates/unresolved links, or custom graph analysis; do not replace normal retrieval with this. Start with gno_query for content questions, then graph tools for relationship context, then gno_get for targeted reads.",
1234
- graphInputSchema.shape,
1321
+ {
1322
+ description:
1323
+ "Get graph report/stats plus nodes/edges for corpus navigation. Use for unfamiliar corpus structure, hubs/isolates/unresolved links, or custom graph analysis; do not replace normal retrieval with this. Start with gno_query for content questions, then graph tools for relationship context, then gno_get for targeted reads.",
1324
+ inputSchema: graphInputSchema,
1325
+ },
1235
1326
  (args) => handleGraph(args, ctx)
1236
1327
  );
1237
1328
 
1238
- server.tool(
1329
+ registerTool(
1239
1330
  "gno_graph_query",
1240
- "Run bounded traversal over typed doc_edges from one root document. Use for explicit relationship questions like 'what does Alice work_at within 2 hops?' or to inspect typed graph hints; returns schemaVersion, root, nodes, edges, caps, and truncation.",
1241
- graphQueryInputSchema.shape,
1331
+ {
1332
+ description:
1333
+ "Run bounded traversal over typed doc_edges from one root document. Use for explicit relationship questions like 'what does Alice work_at within 2 hops?' or to inspect typed graph hints; returns schemaVersion, root, nodes, edges, caps, and truncation.",
1334
+ inputSchema: graphQueryInputSchema,
1335
+ },
1242
1336
  (args) => handleGraphQuery(args, ctx)
1243
1337
  );
1244
1338
 
1245
- server.tool(
1339
+ registerTool(
1246
1340
  "gno_graph_neighbors",
1247
- "Find graph neighbors around a document/node. Use for relationship questions, missed obvious related docs, or unfamiliar corpus navigation after gno_query identifies a seed; returns incoming/outgoing wiki, markdown, and optional similarity edges. Follow with gno_get for targeted reads.",
1248
- graphNeighborsInputSchema.shape,
1341
+ {
1342
+ description:
1343
+ "Find graph neighbors around a document/node. Use for relationship questions, missed obvious related docs, or unfamiliar corpus navigation after gno_query identifies a seed; returns incoming/outgoing wiki, markdown, and optional similarity edges. Follow with gno_get for targeted reads.",
1344
+ inputSchema: graphNeighborsInputSchema,
1345
+ },
1249
1346
  (args) => handleGraphNeighbors(args, ctx)
1250
1347
  );
1251
1348
 
1252
- server.tool(
1349
+ registerTool(
1253
1350
  "gno_graph_path",
1254
- "Find the shortest relationship path between two documents/nodes. Use for prompts like 'how are X and Y connected?' or to explain corpus relationships. Use gno_query for finding candidate refs first, then gno_get on path nodes for evidence.",
1255
- graphPathInputSchema.shape,
1351
+ {
1352
+ description:
1353
+ "Find the shortest relationship path between two documents/nodes. Use for prompts like 'how are X and Y connected?' or to explain corpus relationships. Use gno_query for finding candidate refs first, then gno_get on path nodes for evidence.",
1354
+ inputSchema: graphPathInputSchema,
1355
+ },
1256
1356
  (args) => handleGraphPath(args, ctx)
1257
1357
  );
1258
1358
 
1259
1359
  if (ctx.enableWrite) {
1260
- server.registerTool(
1360
+ registerTool(
1261
1361
  "gno_egress_policy_set",
1262
1362
  {
1263
1363
  description:
@@ -1267,7 +1367,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1267
1367
  (args) => handleEgressPolicySet(args, ctx)
1268
1368
  );
1269
1369
 
1270
- server.registerTool(
1370
+ registerTool(
1271
1371
  "gno_egress_audit_delete",
1272
1372
  {
1273
1373
  description:
@@ -1277,7 +1377,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1277
1377
  (args) => handleEgressAuditDelete(args, ctx)
1278
1378
  );
1279
1379
 
1280
- server.registerTool(
1380
+ registerTool(
1281
1381
  "gno_egress_audit_purge",
1282
1382
  {
1283
1383
  description:
@@ -1287,91 +1387,142 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1287
1387
  (args) => handleEgressAuditPurge(args, ctx)
1288
1388
  );
1289
1389
 
1290
- server.tool(
1390
+ registerTool(
1291
1391
  "gno_trace_label",
1292
- "Append an explicit relevant, irrelevant, or missing_expected judgment to a local retrieval trace.",
1293
- traceLabelInputSchema.shape,
1392
+ {
1393
+ description:
1394
+ "Append an explicit relevant, irrelevant, or missing_expected judgment to a local retrieval trace.",
1395
+ inputSchema: traceLabelInputSchema,
1396
+ },
1294
1397
  (args) => handleTraceLabel(args, ctx)
1295
1398
  );
1296
1399
 
1297
- server.tool(
1400
+ registerTool(
1298
1401
  "gno_trace_export",
1299
- "Build a deterministic local agentic receipt from one or more immutable terminal retrieval traces.",
1300
- traceExportInputSchema.shape,
1402
+ {
1403
+ description:
1404
+ "Build a deterministic local agentic receipt from one or more immutable terminal retrieval traces.",
1405
+ inputSchema: traceExportInputSchema,
1406
+ },
1301
1407
  (args) => handleTraceExport(args, ctx)
1302
1408
  );
1303
1409
 
1304
- server.tool(
1410
+ registerTool(
1305
1411
  "gno_trace_delete",
1306
- "Delete one private local retrieval trace and all owned receipt records.",
1307
- traceDeleteInputSchema.shape,
1412
+ {
1413
+ description:
1414
+ "Delete one private local retrieval trace and all owned receipt records.",
1415
+ inputSchema: traceDeleteInputSchema,
1416
+ },
1308
1417
  (args) => handleTraceDelete(args, ctx)
1309
1418
  );
1310
1419
 
1311
- server.tool(
1420
+ registerTool(
1312
1421
  "gno_trace_purge",
1313
- "Purge every private local retrieval trace receipt. Requires confirm=true.",
1314
- tracePurgeInputSchema.shape,
1422
+ {
1423
+ description:
1424
+ "Purge every private local retrieval trace receipt. Requires confirm=true.",
1425
+ inputSchema: tracePurgeInputSchema,
1426
+ },
1315
1427
  (args) => handleTracePurge(args, ctx)
1316
1428
  );
1317
1429
 
1318
- server.tool(
1430
+ registerTool(
1431
+ "gno_remember",
1432
+ {
1433
+ description: describe("gno_remember", MCP_TOOL_DESCRIPTIONS.remember),
1434
+ inputSchema: rememberInputSchema,
1435
+ annotations: REMEMBER_MCP_ANNOTATIONS,
1436
+ },
1437
+ (args, request) =>
1438
+ handleRemember(args, ctx, {
1439
+ clientName: server.server.getClientVersion()?.name,
1440
+ sessionId: request.sessionId,
1441
+ requestIdentity: ctx.getRequestIdentity?.(),
1442
+ })
1443
+ );
1444
+
1445
+ registerTool(
1319
1446
  "gno_capture",
1320
- "Create a new document in a collection. Writes to disk. Does NOT auto-embed; run gno_index after to make it searchable via vector search.",
1321
- captureInputSchema.shape,
1447
+ {
1448
+ description: describe(
1449
+ "gno_capture",
1450
+ "Create a new document in a collection. Writes to disk. Does NOT auto-embed; run gno_index after to make it searchable via vector search."
1451
+ ),
1452
+ inputSchema: captureInputSchema,
1453
+ },
1322
1454
  (args) => handleCapture(args, ctx)
1323
1455
  );
1324
1456
 
1325
- server.tool(
1457
+ registerTool(
1326
1458
  "gno_add_collection",
1327
- "Add a directory as a new collection and start indexing. Returns a job ID for tracking.",
1328
- addCollectionInputSchema.shape,
1459
+ {
1460
+ description:
1461
+ "Add a directory as a new collection and start indexing. Returns a job ID for tracking.",
1462
+ inputSchema: addCollectionInputSchema,
1463
+ },
1329
1464
  (args) => handleAddCollection(args, ctx)
1330
1465
  );
1331
1466
 
1332
- server.tool(
1467
+ registerTool(
1333
1468
  "gno_sync",
1334
- "Sync files from disk into the index (FTS only, no embeddings). Does NOT auto-embed; run gno_embed after if vector search needed.",
1335
- syncInputSchema.shape,
1469
+ {
1470
+ description:
1471
+ "Sync files from disk into the index (FTS only, no embeddings). Does NOT auto-embed; run gno_embed after if vector search needed.",
1472
+ inputSchema: syncInputSchema,
1473
+ },
1336
1474
  (args) => handleSync(args, ctx)
1337
1475
  );
1338
1476
 
1339
- server.tool(
1477
+ registerTool(
1340
1478
  "gno_embed",
1341
- "Generate vector embeddings for all unembedded chunks, optionally scoped to one collection. Async: returns a job ID. Poll with gno_job_status.",
1342
- embedInputSchema.shape,
1479
+ {
1480
+ description:
1481
+ "Generate vector embeddings for all unembedded chunks, optionally scoped to one collection. Async: returns a job ID. Poll with gno_job_status.",
1482
+ inputSchema: embedInputSchema,
1483
+ },
1343
1484
  (args) => handleEmbed(args, ctx)
1344
1485
  );
1345
1486
 
1346
- server.tool(
1487
+ registerTool(
1347
1488
  "gno_index",
1348
- "Full index: sync files from disk + generate embeddings. Async: returns a job ID. Poll with gno_job_status.",
1349
- indexInputSchema.shape,
1489
+ {
1490
+ description:
1491
+ "Full index: sync files from disk + generate embeddings. Async: returns a job ID. Poll with gno_job_status.",
1492
+ inputSchema: indexInputSchema,
1493
+ },
1350
1494
  (args) => handleIndex(args, ctx)
1351
1495
  );
1352
1496
 
1353
- server.tool(
1497
+ registerTool(
1354
1498
  "gno_remove_collection",
1355
- "Remove a collection from config and delete its indexed data.",
1356
- removeCollectionInputSchema.shape,
1499
+ {
1500
+ description:
1501
+ "Remove a collection from config and delete its indexed data.",
1502
+ inputSchema: removeCollectionInputSchema,
1503
+ },
1357
1504
  (args) => handleRemoveCollection(args, ctx)
1358
1505
  );
1359
1506
 
1360
- server.tool(
1507
+ registerTool(
1361
1508
  "gno_clear_collection_embeddings",
1362
- "Remove stale or all embeddings for one collection.",
1363
- clearCollectionEmbeddingsInputSchema.shape,
1509
+ {
1510
+ description: "Remove stale or all embeddings for one collection.",
1511
+ inputSchema: clearCollectionEmbeddingsInputSchema,
1512
+ },
1364
1513
  (args) => handleClearCollectionEmbeddings(args, ctx)
1365
1514
  );
1366
1515
 
1367
- server.tool(
1516
+ registerTool(
1368
1517
  "gno_create_folder",
1369
- "Create a folder inside an existing collection.",
1370
- createFolderInputSchema.shape,
1518
+ {
1519
+ description: "Create a folder inside an existing collection.",
1520
+ inputSchema: createFolderInputSchema,
1521
+ },
1371
1522
  (args) => handleCreateFolder(args, ctx)
1372
1523
  );
1373
1524
 
1374
- server.registerTool(
1525
+ registerTool(
1375
1526
  "gno_rename_note",
1376
1527
  {
1377
1528
  description:
@@ -1382,7 +1533,7 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1382
1533
  (args) => handleRenameNote(args, ctx)
1383
1534
  );
1384
1535
 
1385
- server.registerTool(
1536
+ registerTool(
1386
1537
  "gno_move_note",
1387
1538
  {
1388
1539
  description:
@@ -1393,25 +1544,34 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
1393
1544
  (args) => handleMoveNote(args, ctx)
1394
1545
  );
1395
1546
 
1396
- server.tool(
1547
+ registerTool(
1397
1548
  "gno_duplicate_note",
1398
- "Duplicate an editable note into the current or another folder.",
1399
- duplicateNoteInputSchema.shape,
1549
+ {
1550
+ description:
1551
+ "Duplicate an editable note into the current or another folder.",
1552
+ inputSchema: duplicateNoteInputSchema,
1553
+ },
1400
1554
  (args) => handleDuplicateNote(args, ctx)
1401
1555
  );
1402
1556
  }
1403
1557
 
1404
- server.tool(
1558
+ registerTool(
1405
1559
  "gno_job_status",
1406
- "Check status of an async job (embed, index). Returns progress percentage and completion state.",
1407
- jobStatusInputSchema.shape,
1560
+ {
1561
+ description:
1562
+ "Check status of an async job (embed, index). Returns progress percentage and completion state.",
1563
+ inputSchema: jobStatusInputSchema,
1564
+ },
1408
1565
  (args) => handleJobStatus(args, ctx)
1409
1566
  );
1410
1567
 
1411
- server.tool(
1568
+ registerTool(
1412
1569
  "gno_list_jobs",
1413
- "List active and recently completed async jobs with their status and progress.",
1414
- listJobsInputSchema.shape,
1570
+ {
1571
+ description:
1572
+ "List active and recently completed async jobs with their status and progress.",
1573
+ inputSchema: listJobsInputSchema,
1574
+ },
1415
1575
  (args) => handleListJobs(args, ctx)
1416
1576
  );
1417
1577
  }