@unclick/mcp-server 0.2.5 → 0.3.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.
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Supabase backend for UnClick Memory.
3
+ *
4
+ * Cloud mode: data lives in the user's own Supabase project (BYOD).
5
+ * Requires SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY env vars.
6
+ */
7
+ import { createClient } from "@supabase/supabase-js";
8
+ let client = null;
9
+ function getSupabase() {
10
+ if (client)
11
+ return client;
12
+ const url = process.env.SUPABASE_URL;
13
+ const key = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_ANON_KEY;
14
+ if (!url || !key) {
15
+ throw new Error("Missing SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY (or SUPABASE_ANON_KEY) environment variables. " +
16
+ "Set these in your MCP config's env block.");
17
+ }
18
+ client = createClient(url, key, {
19
+ auth: { persistSession: false, autoRefreshToken: false },
20
+ });
21
+ return client;
22
+ }
23
+ async function rpc(fn, params = {}) {
24
+ const sb = getSupabase();
25
+ const { data, error } = await sb.rpc(fn, params);
26
+ if (error)
27
+ throw new Error(`rpc(${fn}) failed: ${error.message}`);
28
+ return data;
29
+ }
30
+ function now() {
31
+ return new Date().toISOString();
32
+ }
33
+ function truncate(s, max = 8000) {
34
+ return s.length > max ? s.slice(0, max) + "\n...[truncated]" : s;
35
+ }
36
+ export class SupabaseBackend {
37
+ constructor() {
38
+ // Verify connection on creation
39
+ getSupabase();
40
+ console.error("UnClick Memory: Supabase cloud mode");
41
+ }
42
+ async getStartupContext(numSessions) {
43
+ return rpc("get_startup_context", { num_sessions: numSessions });
44
+ }
45
+ async searchMemory(query, maxResults) {
46
+ return rpc("search_memory", { search_query: query, max_results: maxResults });
47
+ }
48
+ async searchFacts(query) {
49
+ return rpc("search_facts", { search_query: query });
50
+ }
51
+ async searchLibrary(query) {
52
+ return rpc("search_library", { search_query: query });
53
+ }
54
+ async getLibraryDoc(slug) {
55
+ return rpc("get_library_doc", { doc_slug: slug });
56
+ }
57
+ async listLibrary() {
58
+ return rpc("list_library");
59
+ }
60
+ async writeSessionSummary(data) {
61
+ const sb = getSupabase();
62
+ const { data: row, error } = await sb.from("session_summaries").insert({
63
+ session_id: data.session_id,
64
+ summary: data.summary,
65
+ topics: data.topics,
66
+ open_loops: data.open_loops,
67
+ decisions: data.decisions,
68
+ platform: data.platform,
69
+ duration_minutes: data.duration_minutes,
70
+ }).select().single();
71
+ if (error)
72
+ throw error;
73
+ return { id: row.id };
74
+ }
75
+ async addFact(data) {
76
+ const sb = getSupabase();
77
+ const { data: row, error } = await sb.from("extracted_facts").insert({
78
+ fact: data.fact,
79
+ category: data.category,
80
+ confidence: data.confidence,
81
+ source_session_id: data.source_session_id ?? null,
82
+ source_type: "manual",
83
+ status: "active",
84
+ decay_tier: "hot",
85
+ last_accessed: now(),
86
+ }).select().single();
87
+ if (error)
88
+ throw error;
89
+ return { id: row.id };
90
+ }
91
+ async supersedeFact(oldId, newText, category, confidence) {
92
+ const params = { old_fact_id: oldId, new_fact_text: newText };
93
+ if (category !== undefined)
94
+ params.new_category = category;
95
+ if (confidence !== undefined)
96
+ params.new_confidence = confidence;
97
+ const data = await rpc("supersede_fact", params);
98
+ return String(data);
99
+ }
100
+ async logConversation(data) {
101
+ const sb = getSupabase();
102
+ const { error } = await sb.from("conversation_log").insert({
103
+ session_id: data.session_id,
104
+ role: data.role,
105
+ content: truncate(data.content),
106
+ has_code: data.has_code,
107
+ });
108
+ if (error)
109
+ throw error;
110
+ }
111
+ async getConversationDetail(sessionId) {
112
+ return rpc("get_conversation_detail", { sid: sessionId });
113
+ }
114
+ async storeCode(data) {
115
+ const sb = getSupabase();
116
+ const { data: row, error } = await sb.from("code_dumps").insert({
117
+ session_id: data.session_id,
118
+ language: data.language,
119
+ filename: data.filename ?? null,
120
+ content: truncate(data.content, 50000),
121
+ description: data.description ?? null,
122
+ }).select().single();
123
+ if (error)
124
+ throw error;
125
+ return { id: row.id };
126
+ }
127
+ async getBusinessContext() {
128
+ const sb = getSupabase();
129
+ const { data, error } = await sb.from("business_context").select("*").order("category").order("key");
130
+ if (error)
131
+ throw error;
132
+ return data ?? [];
133
+ }
134
+ async setBusinessContext(category, key, value, priority) {
135
+ const sb = getSupabase();
136
+ const row = {
137
+ category,
138
+ key,
139
+ value: typeof value === "string" ? (() => { try {
140
+ return JSON.parse(value);
141
+ }
142
+ catch {
143
+ return value;
144
+ } })() : value,
145
+ last_accessed: now(),
146
+ decay_tier: "hot",
147
+ };
148
+ if (priority !== undefined)
149
+ row.priority = priority;
150
+ const { error } = await sb.from("business_context")
151
+ .upsert(row, { onConflict: "category,key" })
152
+ .select().single();
153
+ if (error)
154
+ throw error;
155
+ }
156
+ async upsertLibraryDoc(data) {
157
+ const sb = getSupabase();
158
+ const { data: existing } = await sb.from("knowledge_library")
159
+ .select("id, version").eq("slug", data.slug).single();
160
+ if (existing) {
161
+ // DB trigger auto-archives old content and bumps version
162
+ const { error } = await sb.from("knowledge_library").update({
163
+ title: data.title,
164
+ category: data.category,
165
+ content: data.content,
166
+ tags: data.tags,
167
+ last_accessed: now(),
168
+ decay_tier: "hot",
169
+ }).eq("id", existing.id);
170
+ if (error)
171
+ throw error;
172
+ return `Library doc updated: "${data.title}" (v${existing.version + 1})`;
173
+ }
174
+ else {
175
+ const { error } = await sb.from("knowledge_library").insert({
176
+ slug: data.slug,
177
+ title: data.title,
178
+ category: data.category,
179
+ content: data.content,
180
+ tags: data.tags,
181
+ version: 1,
182
+ decay_tier: "hot",
183
+ last_accessed: now(),
184
+ });
185
+ if (error)
186
+ throw error;
187
+ return `Library doc created: "${data.title}" (v1)`;
188
+ }
189
+ }
190
+ async manageDecay() {
191
+ return rpc("manage_decay");
192
+ }
193
+ async getMemoryStatus() {
194
+ const sb = getSupabase();
195
+ const tables = ["business_context", "knowledge_library", "session_summaries", "extracted_facts", "conversation_log", "code_dumps"];
196
+ const counts = {};
197
+ for (const table of tables) {
198
+ const { count } = await sb.from(table).select("*", { count: "exact", head: true });
199
+ counts[table] = count;
200
+ }
201
+ const { data: factTiers } = await sb.from("extracted_facts").select("decay_tier").eq("status", "active");
202
+ const tiers = { hot: 0, warm: 0, cold: 0 };
203
+ for (const row of factTiers ?? []) {
204
+ tiers[row.decay_tier]++;
205
+ }
206
+ return { mode: "supabase", table_counts: counts, fact_decay_tiers: tiers };
207
+ }
208
+ }
209
+ //# sourceMappingURL=supabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../src/memory/supabase.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AAUrE,IAAI,MAAM,GAA0B,IAAI,CAAC;AAEzC,SAAS,WAAW;IAClB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAEnF,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,mGAAmG;YACnG,2CAA2C,CAC5C,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE;QAC9B,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE;KACzD,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,GAAG,CAAc,EAAU,EAAE,SAAkC,EAAE;IAC9E,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAClE,OAAO,IAAS,CAAC;AACnB,CAAC;AAED,SAAS,GAAG;IACV,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS,EAAE,GAAG,GAAG,IAAI;IACrC,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,OAAO,eAAe;IAC1B;QACE,gCAAgC;QAChC,WAAW,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,WAAmB;QACzC,OAAO,GAAG,CAA0B,qBAAqB,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAa,EAAE,UAAkB;QAClD,OAAO,GAAG,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,OAAO,GAAG,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,OAAO,GAAG,CAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,OAAO,GAAG,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,IAAyB;QACjD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC;YACrE,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAe;QAC3B,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC;YACnE,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,IAAI;YACjD,WAAW,EAAE,QAAQ;YACrB,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,KAAK;YACjB,aAAa,EAAE,GAAG,EAAE;SACrB,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,QAAiB,EAAE,UAAmB;QACxF,MAAM,MAAM,GAA4B,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;QACvF,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC;QAC3D,IAAI,UAAU,KAAK,SAAS;YAAE,MAAM,CAAC,cAAc,GAAG,UAAU,CAAC;QACjE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAuB;QAC3C,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC;YACzD,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QACH,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QAC3C,OAAO,GAAG,CAAC,yBAAyB,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAe;QAC7B,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YAC9D,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;YAC/B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC;YACtC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;SACtC,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrG,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QACvB,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,QAAgB,EAAE,GAAW,EAAE,KAAc,EAAE,QAAiB;QACvF,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,GAAG,GAA4B;YACnC,QAAQ;YACR,GAAG;YACH,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;gBAAC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;YAClH,aAAa,EAAE,GAAG,EAAE;YACpB,UAAU,EAAE,KAAK;SAClB,CAAC;QACF,IAAI,QAAQ,KAAK,SAAS;YAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACpD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC;aAChD,MAAM,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;aAC3C,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC;QACrB,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,IAAqB;QAC1C,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC;aAC1D,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QAExD,IAAI,QAAQ,EAAE,CAAC;YACb,yDAAyD;YACzD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC;gBAC1D,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,aAAa,EAAE,GAAG,EAAE;gBACpB,UAAU,EAAE,KAAK;aAClB,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACzB,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;YACvB,OAAO,yBAAyB,IAAI,CAAC,KAAK,OAAO,QAAQ,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC;gBAC1D,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,CAAC;gBACV,UAAU,EAAE,KAAK;gBACjB,aAAa,EAAE,GAAG,EAAE;aACrB,CAAC,CAAC;YACH,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;YACvB,OAAO,yBAAyB,IAAI,CAAC,KAAK,QAAQ,CAAC;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,CAAC,CAAC;QACnI,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzG,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;YAClC,KAAK,CAAC,GAAG,CAAC,UAAgC,CAAC,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;IAC7E,CAAC;CACF"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Shared types for UnClick Memory backends (local + Supabase).
3
+ */
4
+ export interface SessionSummaryInput {
5
+ session_id: string;
6
+ summary: string;
7
+ topics: string[];
8
+ open_loops: string[];
9
+ decisions: string[];
10
+ platform: string;
11
+ duration_minutes?: number;
12
+ }
13
+ export interface FactInput {
14
+ fact: string;
15
+ category: string;
16
+ confidence: number;
17
+ source_session_id?: string;
18
+ }
19
+ export interface ConversationInput {
20
+ session_id: string;
21
+ role: string;
22
+ content: string;
23
+ has_code: boolean;
24
+ }
25
+ export interface CodeInput {
26
+ session_id: string;
27
+ language: string;
28
+ filename?: string;
29
+ content: string;
30
+ description?: string;
31
+ }
32
+ export interface LibraryDocInput {
33
+ slug: string;
34
+ title: string;
35
+ category: string;
36
+ content: string;
37
+ tags: string[];
38
+ }
39
+ export interface MemoryBackend {
40
+ /** Load startup context (business context + recent sessions + hot facts). */
41
+ getStartupContext(numSessions: number): Promise<unknown>;
42
+ /** Full-text search across conversation logs. */
43
+ searchMemory(query: string, maxResults: number): Promise<unknown>;
44
+ /** Search extracted facts. */
45
+ searchFacts(query: string): Promise<unknown>;
46
+ /** Search knowledge library. */
47
+ searchLibrary(query: string): Promise<unknown>;
48
+ /** Get a specific library doc by slug. */
49
+ getLibraryDoc(slug: string): Promise<unknown>;
50
+ /** List all library documents. */
51
+ listLibrary(): Promise<unknown>;
52
+ /** Write end-of-session summary. */
53
+ writeSessionSummary(data: SessionSummaryInput): Promise<{
54
+ id: string;
55
+ }>;
56
+ /** Add an extracted fact. */
57
+ addFact(data: FactInput): Promise<{
58
+ id: string;
59
+ }>;
60
+ /** Replace a fact with a new version. */
61
+ supersedeFact(oldId: string, newText: string, category?: string, confidence?: number): Promise<string>;
62
+ /** Log a conversation message. */
63
+ logConversation(data: ConversationInput): Promise<void>;
64
+ /** Get full conversation log for a session. */
65
+ getConversationDetail(sessionId: string): Promise<unknown>;
66
+ /** Store a code block. */
67
+ storeCode(data: CodeInput): Promise<{
68
+ id: string;
69
+ }>;
70
+ /** Get all business context entries. */
71
+ getBusinessContext(): Promise<unknown[]>;
72
+ /** Set or update a business context entry. */
73
+ setBusinessContext(category: string, key: string, value: unknown, priority?: number): Promise<void>;
74
+ /** Create or update a knowledge library doc. */
75
+ upsertLibraryDoc(data: LibraryDocInput): Promise<string>;
76
+ /** Run memory decay management. */
77
+ manageDecay(): Promise<unknown>;
78
+ /** Get memory usage stats. */
79
+ getMemoryStatus(): Promise<unknown>;
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types for UnClick Memory backends (local + Supabase).
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -39,13 +39,13 @@ export async function listMondayBoards(args) {
39
39
  try {
40
40
  const apiKey = getApiKey(args);
41
41
  const limit = Number(args.limit ?? 25);
42
- const query = `
43
- query($limit: Int) {
44
- boards(limit: $limit) {
45
- id name description state board_kind
46
- columns { id title type }
47
- }
48
- }
42
+ const query = `
43
+ query($limit: Int) {
44
+ boards(limit: $limit) {
45
+ id name description state board_kind
46
+ columns { id title type }
47
+ }
48
+ }
49
49
  `;
50
50
  const data = await mondayQuery(apiKey, query, { limit });
51
51
  const boards = (data.boards ?? []);
@@ -62,14 +62,14 @@ export async function getMondayBoard(args) {
62
62
  const boardId = String(args.board_id ?? "").trim();
63
63
  if (!boardId)
64
64
  return { error: "board_id is required." };
65
- const query = `
66
- query($ids: [ID!]) {
67
- boards(ids: $ids) {
68
- id name description state board_kind
69
- columns { id title type }
70
- groups { id title color }
71
- }
72
- }
65
+ const query = `
66
+ query($ids: [ID!]) {
67
+ boards(ids: $ids) {
68
+ id name description state board_kind
69
+ columns { id title type }
70
+ groups { id title color }
71
+ }
72
+ }
73
73
  `;
74
74
  const data = await mondayQuery(apiKey, query, { ids: [boardId] });
75
75
  const boards = (data.boards ?? []);
@@ -87,18 +87,18 @@ export async function listMondayItems(args) {
87
87
  if (!boardId)
88
88
  return { error: "board_id is required." };
89
89
  const limit = Number(args.limit ?? 50);
90
- const query = `
91
- query($ids: [ID!], $limit: Int) {
92
- boards(ids: $ids) {
93
- items_page(limit: $limit) {
94
- items {
95
- id name state created_at updated_at
96
- column_values { id text value }
97
- group { id title }
98
- }
99
- }
100
- }
101
- }
90
+ const query = `
91
+ query($ids: [ID!], $limit: Int) {
92
+ boards(ids: $ids) {
93
+ items_page(limit: $limit) {
94
+ items {
95
+ id name state created_at updated_at
96
+ column_values { id text value }
97
+ group { id title }
98
+ }
99
+ }
100
+ }
101
+ }
102
102
  `;
103
103
  const data = await mondayQuery(apiKey, query, { ids: [boardId], limit });
104
104
  const boards = (data.boards ?? []);
@@ -120,12 +120,12 @@ export async function createMondayItem(args) {
120
120
  const itemName = String(args.item_name ?? "").trim();
121
121
  if (!itemName)
122
122
  return { error: "item_name is required." };
123
- const mutation = `
124
- mutation($board_id: ID!, $item_name: String!, $group_id: String, $column_values: JSON) {
125
- create_item(board_id: $board_id, item_name: $item_name, group_id: $group_id, column_values: $column_values) {
126
- id name state created_at
127
- }
128
- }
123
+ const mutation = `
124
+ mutation($board_id: ID!, $item_name: String!, $group_id: String, $column_values: JSON) {
125
+ create_item(board_id: $board_id, item_name: $item_name, group_id: $group_id, column_values: $column_values) {
126
+ id name state created_at
127
+ }
128
+ }
129
129
  `;
130
130
  const variables = { board_id: boardId, item_name: itemName };
131
131
  if (args.group_id)
@@ -157,12 +157,12 @@ export async function updateMondayItem(args) {
157
157
  const value = args.value;
158
158
  if (value === undefined)
159
159
  return { error: "value is required." };
160
- const mutation = `
161
- mutation($board_id: ID!, $item_id: ID!, $column_id: String!, $value: JSON!) {
162
- change_column_value(board_id: $board_id, item_id: $item_id, column_id: $column_id, value: $value) {
163
- id name
164
- }
165
- }
160
+ const mutation = `
161
+ mutation($board_id: ID!, $item_id: ID!, $column_id: String!, $value: JSON!) {
162
+ change_column_value(board_id: $board_id, item_id: $item_id, column_id: $column_id, value: $value) {
163
+ id name
164
+ }
165
+ }
166
166
  `;
167
167
  const data = await mondayQuery(apiKey, mutation, {
168
168
  board_id: boardId,
@@ -187,13 +187,13 @@ export async function searchMondayItems(args) {
187
187
  if (!query_text)
188
188
  return { error: "query is required." };
189
189
  const limit = Number(args.limit ?? 25);
190
- const query = `
191
- query($board_id: ID!, $query: String!, $limit: Int) {
192
- items_by_multiple_column_values(board_id: $board_id, limit: $limit, column_id: "name", column_values: [$query]) {
193
- id name state created_at updated_at
194
- column_values { id text value }
195
- }
196
- }
190
+ const query = `
191
+ query($board_id: ID!, $query: String!, $limit: Int) {
192
+ items_by_multiple_column_values(board_id: $board_id, limit: $limit, column_id: "name", column_values: [$query]) {
193
+ id name state created_at updated_at
194
+ column_values { id text value }
195
+ }
196
+ }
197
197
  `;
198
198
  const data = await mondayQuery(apiKey, query, { board_id: boardId, query: query_text, limit });
199
199
  const items = (data.items_by_multiple_column_values ?? []);
@@ -2,7 +2,7 @@
2
2
  // Uses the MusicBrainz REST API via fetch - no external dependencies.
3
3
  // No auth required. Identifies with a User-Agent header as required by MusicBrainz policy.
4
4
  const MB_BASE = "https://musicbrainz.org/ws/2";
5
- const MB_USER_AGENT = "UnClick/1.0 (creativelead@malamutemayhem.com)";
5
+ const MB_USER_AGENT = "UnClick/1.0 (support@unclick.world)";
6
6
  // ─── API helper ───────────────────────────────────────────────────────────────
7
7
  async function mbCall(path, params = {}) {
8
8
  const url = new URL(`${MB_BASE}${path}`);
@@ -1 +1 @@
1
- {"version":3,"file":"musicbrainz-tool.js","sourceRoot":"","sources":["../src/musicbrainz-tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"musicbrainz-tool.js","sourceRoot":"","sources":["../src/musicbrainz-tool.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,sEAAsE;AACtE,2FAA2F;AAE3F,MAAM,OAAO,GAAG,8BAA8B,CAAC;AAC/C,MAAM,aAAa,GAAG,qCAAqC,CAAC;AAE5D,iFAAiF;AAEjF,KAAK,UAAU,MAAM,CACnB,IAAY,EACZ,SAAsD,EAAE;IAExD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,CAAC,CAAC;IACzC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEpC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAC/C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QAC3C,OAAO,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE;KACzC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,uBAAuB,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAA6B;IACjE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,OAAO,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAA6B;IAClE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAExE,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,SAAS,GAAG,GAAG,KAAK,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAA6B;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAExE,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,SAAS,GAAG,GAAG,KAAK,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAA6B;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAA6B;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA6fnE,wBAAgB,YAAY,IAAI,MAAM,CAuNrC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA8lBnE,wBAAgB,YAAY,IAAI,MAAM,CAqPrC;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjD"}
package/dist/server.js CHANGED
@@ -5,6 +5,7 @@ import { CATALOG, TOOL_MAP, ENDPOINT_MAP } from "./catalog.js";
5
5
  import { createClient } from "./client.js";
6
6
  import { ADDITIONAL_HANDLERS } from "./tool-wiring.js";
7
7
  import { LOCAL_CATALOG_HANDLERS } from "./local-catalog-handlers.js";
8
+ import { MEMORY_HANDLERS } from "./memory/handlers.js";
8
9
  // ─── Search helper ──────────────────────────────────────────────────────────
9
10
  function searchTools(query, category) {
10
11
  const q = query.toLowerCase();
@@ -105,6 +106,97 @@ const META_TOOLS = [
105
106
  required: ["endpoint_id", "params"],
106
107
  },
107
108
  },
109
+ // ── UnClick Memory (persistent cross-session memory) ─────────────────────
110
+ // These 5 tools implement the session-start / session-end protocol agents
111
+ // should follow. The other 12 memory operations are available via unclick_call
112
+ // with endpoint_id like "memory.add_fact", "memory.search_memory", etc.
113
+ {
114
+ name: "get_startup_context",
115
+ description: "Load persistent UnClick Memory at session start. Returns business context (standing rules), " +
116
+ "recent session summaries, and hot facts. Call this FIRST in every new session to understand " +
117
+ "the user's ongoing projects, preferences, and open loops. Works zero-config locally, or with " +
118
+ "Supabase for cross-machine sync.",
119
+ inputSchema: {
120
+ type: "object",
121
+ properties: {
122
+ num_sessions: {
123
+ type: "number",
124
+ description: "Number of recent session summaries to load (1-20, default 5)",
125
+ default: 5,
126
+ },
127
+ },
128
+ },
129
+ },
130
+ {
131
+ name: "write_session_summary",
132
+ description: "Write a session summary at the end of a session. Critical for cross-session continuity. " +
133
+ "Call this BEFORE the session ends (when the user says goodbye, or context is running low). " +
134
+ "Include key decisions, open loops, and topics discussed.",
135
+ inputSchema: {
136
+ type: "object",
137
+ properties: {
138
+ session_id: { type: "string", description: "Unique session identifier (timestamp or UUID)" },
139
+ summary: { type: "string", description: "Narrative of what happened - decisions, work completed, problems solved" },
140
+ topics: { type: "array", items: { type: "string" }, description: "Topic tags for searchability" },
141
+ open_loops: { type: "array", items: { type: "string" }, description: "Unfinished tasks or questions to carry forward" },
142
+ decisions: { type: "array", items: { type: "string" }, description: "Key decisions made during the session" },
143
+ platform: { type: "string", description: "Platform this session ran on", default: "claude-code" },
144
+ duration_minutes: { type: "number", description: "Approximate session duration" },
145
+ },
146
+ required: ["session_id", "summary"],
147
+ },
148
+ },
149
+ {
150
+ name: "add_fact",
151
+ description: "Add a new atomic fact to UnClick Memory. One fact = one statement. " +
152
+ "Use when the user states a preference, makes a decision, or shares important info. " +
153
+ "Good: 'Team prefers Tailwind over CSS modules'. Bad: 'We talked about styling'.",
154
+ inputSchema: {
155
+ type: "object",
156
+ properties: {
157
+ fact: { type: "string", description: "The fact - a single atomic statement" },
158
+ category: {
159
+ type: "string",
160
+ description: "Category: preference, decision, technical, contact, project, general",
161
+ default: "general",
162
+ },
163
+ confidence: { type: "number", minimum: 0, maximum: 1, default: 0.9 },
164
+ source_session_id: { type: "string", description: "Session ID where this fact was learned" },
165
+ },
166
+ required: ["fact"],
167
+ },
168
+ },
169
+ {
170
+ name: "search_memory",
171
+ description: "Full-text search across UnClick Memory conversation logs. Use when you need to recall " +
172
+ "something specific from a previous session.",
173
+ inputSchema: {
174
+ type: "object",
175
+ properties: {
176
+ query: { type: "string", description: "Search query" },
177
+ max_results: { type: "number", minimum: 1, maximum: 50, default: 10 },
178
+ },
179
+ required: ["query"],
180
+ },
181
+ },
182
+ {
183
+ name: "set_business_context",
184
+ description: "Add or update a standing rule in UnClick Memory (Layer 1). Business context is ALWAYS loaded " +
185
+ "at session start. Use for standing rules, client info, and preferences that are always relevant.",
186
+ inputSchema: {
187
+ type: "object",
188
+ properties: {
189
+ category: {
190
+ type: "string",
191
+ description: "Category: identity, preference, client, workflow, technical, standing_rule",
192
+ },
193
+ key: { type: "string", description: "Unique key within category (e.g. 'timezone', 'preferred_stack')" },
194
+ value: { type: "string", description: "The value to store (plain text or JSON string)" },
195
+ priority: { type: "number", description: "Priority for loading order (higher = loaded first)" },
196
+ },
197
+ required: ["category", "key", "value"],
198
+ },
199
+ },
108
200
  ];
109
201
  const DIRECT_TOOLS = [
110
202
  {
@@ -468,6 +560,13 @@ export function createServer() {
468
560
  const { name, arguments: rawArgs } = request.params;
469
561
  const args = (rawArgs ?? {});
470
562
  try {
563
+ // ── UnClick Memory (direct tools + memory.* endpoints) ───────
564
+ if (MEMORY_HANDLERS[name]) {
565
+ const result = await MEMORY_HANDLERS[name](args);
566
+ return {
567
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
568
+ };
569
+ }
471
570
  // ── Meta tools ──────────────────────────────────────────────
472
571
  if (name === "unclick_search") {
473
572
  const results = searchTools(String(args.query ?? ""), args.category);
@@ -557,6 +656,17 @@ export function createServer() {
557
656
  if (name === "unclick_call") {
558
657
  const endpointId = String(args.endpoint_id ?? "");
559
658
  const params = (args.params ?? {});
659
+ // Memory endpoints: "memory.add_fact", "memory.store_code", etc.
660
+ if (endpointId.startsWith("memory.")) {
661
+ const op = endpointId.slice("memory.".length);
662
+ const memHandler = MEMORY_HANDLERS[op];
663
+ if (memHandler) {
664
+ const result = await memHandler(params);
665
+ return {
666
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
667
+ };
668
+ }
669
+ }
560
670
  // Check local handlers first (avoids remote API dependency)
561
671
  const localHandler = LOCAL_CATALOG_HANDLERS[endpointId];
562
672
  if (localHandler) {
@@ -577,6 +687,15 @@ export function createServer() {
577
687
  isError: true,
578
688
  };
579
689
  }
690
+ // Try ADDITIONAL_HANDLERS via dot-to-underscore key conversion ("foo.bar" -> "foo_bar")
691
+ const handlerKey = endpointId.replace(/\./g, "_");
692
+ const additionalHandler = ADDITIONAL_HANDLERS[handlerKey];
693
+ if (additionalHandler) {
694
+ const result = await additionalHandler(params);
695
+ return {
696
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
697
+ };
698
+ }
580
699
  // Fall back to remote API for endpoints without local implementations
581
700
  const client = createClient();
582
701
  const result = await client.call(entry.endpoint.method, entry.endpoint.path, params);