@justmpm/memory 0.1.2 → 0.2.2
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.
- package/AGENTS.md +45 -640
- package/CHANGELOG.md +42 -0
- package/CLAUDE.md +74 -180
- package/README.md +277 -281
- package/dist/index.js +216 -387
- package/dist/index.js.map +1 -1
- package/package.json +41 -40
- package/src/index.ts +538 -692
package/dist/index.js
CHANGED
|
@@ -10,9 +10,41 @@
|
|
|
10
10
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
11
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
12
12
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync,
|
|
13
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, } from "fs";
|
|
14
14
|
import { join, dirname } from "path";
|
|
15
15
|
import { fileURLToPath } from "url";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
18
|
+
// SCHEMAS DE VALIDAÇÃO (Zod)
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
/**
|
|
21
|
+
* Schema para tool memory_read
|
|
22
|
+
*/
|
|
23
|
+
const MemoryReadSchema = z.object({
|
|
24
|
+
agent: z.string().optional().describe('Seu nome de agent (ex: "sentinel", "fix-worker"). Opcional - usa "unknown" se não informado.'),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Schema para tool memory_append
|
|
28
|
+
*/
|
|
29
|
+
const MemoryAppendSchema = z.object({
|
|
30
|
+
agent: z.string().optional().describe('Seu nome de agent (ex: "sentinel", "fix-worker"). Opcional - usa "unknown" se não informado.'),
|
|
31
|
+
entry: z.string().min(1).describe('Texto da informação a salvar. Ex: "Padrão: sempre use try/catch em funções async" ou "Bug: erro quando usuário clica 2x". Será adicionado com timestamp automaticamente.'),
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Schema para tool memory_search
|
|
35
|
+
*/
|
|
36
|
+
const MemorySearchSchema = z.object({
|
|
37
|
+
agent: z.string().optional().describe('Seu nome de agent (ex: "sentinel", "fix-worker"). Opcional - usa "unknown" se não informado.'),
|
|
38
|
+
query: z.string().min(1).describe('Palavra-chave para buscar na sua memória. Ex: "Zod", "bug", "Firebase". Retorna até 20 resultados com número da linha.'),
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Schema para tool memory_write
|
|
42
|
+
*/
|
|
43
|
+
const MemoryWriteSchema = z.object({
|
|
44
|
+
agent: z.string().optional().describe('Seu nome de agent (ex: "sentinel", "fix-worker"). Opcional - usa "unknown" se não informado.'),
|
|
45
|
+
content: z.string().min(1).describe('Conteúdo completo em markdown para substituir a memória existente. Use para reorganizar, limpar ou reconstruir memória do zero.'),
|
|
46
|
+
backup: z.boolean().optional().default(false).describe('Se true, cria um backup do conteúdo atual antes de sobrescrever. O backup é salvo como MEMORY.md.backup no mesmo diretório.'),
|
|
47
|
+
});
|
|
16
48
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
17
49
|
// VERSÃO DO PROJETO
|
|
18
50
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -83,29 +115,12 @@ function limitMemoryLines(content, maxLines = 200) {
|
|
|
83
115
|
return content;
|
|
84
116
|
const keepCount = Math.floor(maxLines * 0.8); // 160 linhas
|
|
85
117
|
const removed = lines.length - keepCount;
|
|
86
|
-
return `# Memória (últimas ${keepCount} de ${lines.length} linhas)
|
|
87
|
-
|
|
88
|
-
[... ${removed} linhas anteriores removidas ...]
|
|
89
|
-
|
|
118
|
+
return `# Memória (últimas ${keepCount} de ${lines.length} linhas)
|
|
119
|
+
|
|
120
|
+
[... ${removed} linhas anteriores removidas ...]
|
|
121
|
+
|
|
90
122
|
${lines.slice(-keepCount).join("\n")}`;
|
|
91
123
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Lista todos os agents que têm memória
|
|
94
|
-
*/
|
|
95
|
-
function listAgentsWithMemory() {
|
|
96
|
-
const memoryRoot = join(process.cwd(), ".claude", "agent-memory");
|
|
97
|
-
if (!existsSync(memoryRoot))
|
|
98
|
-
return [];
|
|
99
|
-
try {
|
|
100
|
-
return readdirSync(memoryRoot).filter((name) => {
|
|
101
|
-
const memoryPath = join(memoryRoot, name, "MEMORY.md");
|
|
102
|
-
return existsSync(memoryPath);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
124
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
110
125
|
// HANDLERS DAS OPERAÇÕES
|
|
111
126
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -115,17 +130,17 @@ function listAgentsWithMemory() {
|
|
|
115
130
|
async function handleRead(agentName) {
|
|
116
131
|
const memoryPath = getAgentMemoryPath(agentName);
|
|
117
132
|
if (!existsSync(memoryPath)) {
|
|
118
|
-
return `📝 Memória vazia para agent "${agentName}".
|
|
119
|
-
|
|
133
|
+
return `📝 Memória vazia para agent "${agentName}".
|
|
134
|
+
|
|
120
135
|
Use \`command="append", entry="..."\` para criar a primeira entrada.`;
|
|
121
136
|
}
|
|
122
137
|
try {
|
|
123
138
|
const content = readFileSync(memoryPath, "utf-8");
|
|
124
139
|
const lines = content.split("\n").length;
|
|
125
|
-
return `📝 Memória de "${agentName}" (${lines} linhas):
|
|
126
|
-
|
|
127
|
-
─────────────────────────────────────────────────────────────────
|
|
128
|
-
|
|
140
|
+
return `📝 Memória de "${agentName}" (${lines} linhas):
|
|
141
|
+
|
|
142
|
+
─────────────────────────────────────────────────────────────────
|
|
143
|
+
|
|
129
144
|
${content}`;
|
|
130
145
|
}
|
|
131
146
|
catch (error) {
|
|
@@ -135,14 +150,23 @@ ${content}`;
|
|
|
135
150
|
/**
|
|
136
151
|
* Handler: write - Substitui toda a memória
|
|
137
152
|
*/
|
|
138
|
-
async function handleWrite(agentName, content) {
|
|
153
|
+
async function handleWrite(agentName, content, backup = false) {
|
|
139
154
|
try {
|
|
140
155
|
ensureAgentMemoryDir(agentName);
|
|
156
|
+
const memoryPath = getAgentMemoryPath(agentName);
|
|
157
|
+
// Cria backup se solicitado e arquivo existir
|
|
158
|
+
let backupMessage = "";
|
|
159
|
+
if (backup && existsSync(memoryPath)) {
|
|
160
|
+
const backupPath = memoryPath + ".backup";
|
|
161
|
+
const existingContent = readFileSync(memoryPath, "utf-8");
|
|
162
|
+
writeFileSync(backupPath, existingContent, "utf-8");
|
|
163
|
+
backupMessage = `\n💾 Backup criado: MEMORY.md.backup`;
|
|
164
|
+
}
|
|
141
165
|
const limited = limitMemoryLines(content);
|
|
142
|
-
writeFileSync(
|
|
166
|
+
writeFileSync(memoryPath, limited, "utf-8");
|
|
143
167
|
const lines = limited.split("\n").length;
|
|
144
|
-
return `✅ Memória de "${agentName}" atualizada (${lines} linhas)
|
|
145
|
-
|
|
168
|
+
return `✅ Memória de "${agentName}" atualizada (${lines} linhas).${backupMessage}
|
|
169
|
+
|
|
146
170
|
${lines >= 200 ? "⚠️ Memória atingiu o limite de 200 linhas." : ""}`;
|
|
147
171
|
}
|
|
148
172
|
catch (error) {
|
|
@@ -168,9 +192,9 @@ async function handleAppend(agentName, entry) {
|
|
|
168
192
|
// Salva com limite
|
|
169
193
|
const limited = limitMemoryLines(newContent);
|
|
170
194
|
writeFileSync(memoryPath, limited, "utf-8");
|
|
171
|
-
return `✅ Entrada adicionada à memória de "${agentName}".
|
|
172
|
-
|
|
173
|
-
**Timestamp:** ${timestamp}
|
|
195
|
+
return `✅ Entrada adicionada à memória de "${agentName}".
|
|
196
|
+
|
|
197
|
+
**Timestamp:** ${timestamp}
|
|
174
198
|
**Entry:** ${entry.slice(0, 100)}${entry.length > 100 ? "..." : ""}`;
|
|
175
199
|
}
|
|
176
200
|
catch (error) {
|
|
@@ -200,41 +224,14 @@ async function handleSearch(agentName, query) {
|
|
|
200
224
|
.map(({ line, idx }) => ` L${idx + 1}: ${line}`)
|
|
201
225
|
.join("\n");
|
|
202
226
|
const more = matches.length > 20 ? `\n... e mais ${matches.length - 20} ocorrências` : "";
|
|
203
|
-
return `📝 Busca por "${query}" em "${agentName}" (${matches.length} ocorrências):
|
|
204
|
-
|
|
227
|
+
return `📝 Busca por "${query}" em "${agentName}" (${matches.length} ocorrências):
|
|
228
|
+
|
|
205
229
|
${results}${more}`;
|
|
206
230
|
}
|
|
207
231
|
catch (error) {
|
|
208
232
|
return `❌ Erro ao buscar: ${error.message}`;
|
|
209
233
|
}
|
|
210
234
|
}
|
|
211
|
-
/**
|
|
212
|
-
* Handler: list - Lista todos os agents com memória
|
|
213
|
-
*/
|
|
214
|
-
async function handleList() {
|
|
215
|
-
const agents = listAgentsWithMemory();
|
|
216
|
-
if (agents.length === 0) {
|
|
217
|
-
return `📝 Nenhum agent com memória neste projeto.
|
|
218
|
-
|
|
219
|
-
Diretório: .claude/agent-memory/`;
|
|
220
|
-
}
|
|
221
|
-
const agentList = agents
|
|
222
|
-
.map((name) => {
|
|
223
|
-
const path = join(".claude", "agent-memory", name, "MEMORY.md");
|
|
224
|
-
let lines = 0;
|
|
225
|
-
try {
|
|
226
|
-
lines = readFileSync(join(process.cwd(), path), "utf-8").split("\n").length;
|
|
227
|
-
}
|
|
228
|
-
catch { }
|
|
229
|
-
return ` • ${name} (${lines} linhas)`;
|
|
230
|
-
})
|
|
231
|
-
.join("\n");
|
|
232
|
-
return `📝 Agents com memória neste projeto (${agents.length}):
|
|
233
|
-
|
|
234
|
-
${agentList}
|
|
235
|
-
|
|
236
|
-
Use o comando "read" de cada agent para ver o conteúdo.`;
|
|
237
|
-
}
|
|
238
235
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
239
236
|
// SERVIDOR MCP
|
|
240
237
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -253,198 +250,94 @@ const server = new Server({
|
|
|
253
250
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
254
251
|
return {
|
|
255
252
|
tools: [
|
|
253
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
254
|
+
// TOOL: memory_read
|
|
255
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
256
256
|
{
|
|
257
|
-
name: "
|
|
258
|
-
description: `
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
{ "command": "read", "agent": "sentinel" }
|
|
342
|
-
|
|
343
|
-
Exemplo 2 - Salvar padrão descoberto:
|
|
344
|
-
{ "command": "append", "agent": "sentinel", "entry": "Padrão: Sempre use Zod para validar inputs do usuário em todos os componentes de formulário" }
|
|
345
|
-
|
|
346
|
-
Exemplo 3 - Salvar decisão arquitetural:
|
|
347
|
-
{ "command": "append", "agent": "nexus", "entry": "Decisão: Usar Zustand para estado global (mais leve que Redux) - Projeto tem até 5 stores independentes" }
|
|
348
|
-
|
|
349
|
-
Exemplo 4 - Buscar informações sobre Zod:
|
|
350
|
-
{ "command": "search", "agent": "sentinel", "query": "Zod" }
|
|
351
|
-
|
|
352
|
-
Exemplo 5 - Reorganizar memória grande:
|
|
353
|
-
{ "command": "write", "agent": "sentinel", "content": "# Memória do Sentinel\\n\\n## Padrões\\n- Use Zod para validação\\n\\n## Bugs\\n- Bug XYZ: ocorre quando..." }
|
|
354
|
-
|
|
355
|
-
Exemplo 6 - Listar todos os agents:
|
|
356
|
-
{ "command": "list" }
|
|
357
|
-
|
|
358
|
-
═══════════════════════════════════════════════════════════════
|
|
359
|
-
BOAS PRÁTICAS (O QUE SALVAR):
|
|
360
|
-
═══════════════════════════════════════════════════════════════
|
|
361
|
-
|
|
362
|
-
✅ **SEMPRE salve:**
|
|
363
|
-
- Padrões de código descobertos (ex: "Sempre use 2 espaços de indentação em TSX")
|
|
364
|
-
- Decisões arquiteturais (ex: "Escolhemos Firestore em vez de PostgreSQL porque...")
|
|
365
|
-
- Bugs recorrentes (ex: "Erro X acontece quando...")
|
|
366
|
-
- Soluções para problemas específicos (ex: "Para resolver problema Y, use...")
|
|
367
|
-
- Configurações importantes (ex: "Firebase Auth usa Google Sign-In")
|
|
368
|
-
- Preferências do usuário (ex: "Matheus prefere estilos inline para componentes simples")
|
|
369
|
-
|
|
370
|
-
✅ **Use markdown organizado:**
|
|
371
|
-
## Padrões - Padrões de código e convenções
|
|
372
|
-
## Decisões - Escolhas arquiteturais e trade-offs
|
|
373
|
-
## Bugs - Problemas conhecidos e workarounds
|
|
374
|
-
## Configurações - Configs e setup específicos
|
|
375
|
-
## Preferências - Preferências pessoais do usuário
|
|
376
|
-
|
|
377
|
-
✅ **Adicione contexto:**
|
|
378
|
-
- "No projeto X, use Y..." (especifica o projeto)
|
|
379
|
-
- "Ao trabalhar com componente Z..." (especifica o contexto)
|
|
380
|
-
- "Quando acontecer erro Y..." (especifica a condição)
|
|
381
|
-
|
|
382
|
-
═══════════════════════════════════════════════════════════════
|
|
383
|
-
BOAS PRÁTICAS (O QUE NÃO SALVAR):
|
|
384
|
-
═══════════════════════════════════════════════════════════════
|
|
385
|
-
|
|
386
|
-
❌ **NÃO salve:**
|
|
387
|
-
- Coisas triviais (ex: "Hoje está chovendo")
|
|
388
|
-
- Informações que mudam frequentemente (ex: "Tem 3 arquivos na pasta")
|
|
389
|
-
- Coisas que são óbvias (ex: "O código precisa compilar")
|
|
390
|
-
- Informações duplicadas
|
|
391
|
-
- Logs de conversação
|
|
392
|
-
- Erros temporários que já foram resolvidos
|
|
393
|
-
|
|
394
|
-
❌ **NÃO repita:**
|
|
395
|
-
- Se um padrão já está salvo, não salve novamente
|
|
396
|
-
- Use search para verificar antes de salvar
|
|
397
|
-
|
|
398
|
-
═══════════════════════════════════════════════════════════════
|
|
399
|
-
IMPORTANTE:
|
|
400
|
-
═══════════════════════════════════════════════════════════════
|
|
401
|
-
|
|
402
|
-
• O nome do agent é NORMALIZADO automaticamente:
|
|
403
|
-
- "Sentinel" → "sentinel"
|
|
404
|
-
- "QA-Tester" → "qa-tester"
|
|
405
|
-
- "My Agent" → "my-agent"
|
|
406
|
-
|
|
407
|
-
• O parâmetro 'agent' é OPCIONAL:
|
|
408
|
-
- Se não fornecido, usa "unknown" como nome padrão
|
|
409
|
-
- É recomendável SEMPRE fornecer o nome do agent atual
|
|
410
|
-
|
|
411
|
-
• Memória é específica por projeto:
|
|
412
|
-
- Cada projeto tem sua própria pasta .claude/agent-memory/
|
|
413
|
-
- Memórias de diferentes projetos não se misturam
|
|
414
|
-
|
|
415
|
-
• Quando a memória atinge 200 linhas:
|
|
416
|
-
- As primeiras entradas mais antigas são removidas automaticamente
|
|
417
|
-
- Mantém as últimas 160 linhas mais recentes
|
|
418
|
-
- Adiciona cabeçalho informando sobre a limpeza
|
|
419
|
-
- Use write para reorganizar se isso acontecer com frequência
|
|
420
|
-
`.trim(),
|
|
421
|
-
inputSchema: {
|
|
422
|
-
type: "object",
|
|
423
|
-
properties: {
|
|
424
|
-
command: {
|
|
425
|
-
type: "string",
|
|
426
|
-
enum: ["read", "write", "append", "search", "list"],
|
|
427
|
-
description: "Comando a executar. 'read' carrega memória, 'write' substitui tudo, 'append' adiciona entrada, 'search' busca termo, 'list' mostra agents.",
|
|
428
|
-
},
|
|
429
|
-
agent: {
|
|
430
|
-
type: "string",
|
|
431
|
-
description: 'Nome do agent (opcional, usa "unknown" se não fornecido). O nome será normalizado (lowercase, hífens). Ex: "Sentinel", "QA-Tester", "My Agent"',
|
|
432
|
-
},
|
|
433
|
-
content: {
|
|
434
|
-
type: "string",
|
|
435
|
-
description: 'Conteúdo completo em markdown para substituir a memória existente (OBRIGATÓRIO para "write"). Use para reorganizar, limpar ou reconstruir memória do zero.',
|
|
436
|
-
},
|
|
437
|
-
entry: {
|
|
438
|
-
type: "string",
|
|
439
|
-
description: 'Texto da entrada a adicionar no final da memória (OBRIGATÓRIO para "append"). Será prefixado automaticamente com timestamp "## [YYYY-MM-DD HH:MM:SS]". Use para salvar aprendizados incrementais.',
|
|
440
|
-
},
|
|
441
|
-
query: {
|
|
442
|
-
type: "string",
|
|
443
|
-
description: 'Termo ou padrão de busca case-insensitive (OBRIGATÓRIO para "search"). Retorna até 20 ocorrências com número da linha. Ex: "Zod", "bug", "Firebase"',
|
|
444
|
-
},
|
|
445
|
-
},
|
|
446
|
-
required: ["command"],
|
|
447
|
-
},
|
|
257
|
+
name: "memory_read",
|
|
258
|
+
description: `Lê todo o conteúdo da sua memória persistente. Use sempre ao iniciar uma sessão para recuperar contexto anterior.
|
|
259
|
+
|
|
260
|
+
RETORNA: Conteúdo completo do MEMORY.md localizado em .claude/agent-memory/<agent-name>/MEMORY.md.
|
|
261
|
+
|
|
262
|
+
Se a memória não existir, retorna mensagem de memória vazia com sugestão para usar memory_append.
|
|
263
|
+
|
|
264
|
+
Limite: Máximo 200 linhas. Ao atingir, mantém apenas as últimas 160 entradas.
|
|
265
|
+
|
|
266
|
+
Parâmetro "agent": Seu nome de agent (opcional, padrão: "unknown").`,
|
|
267
|
+
inputSchema: MemoryReadSchema,
|
|
268
|
+
},
|
|
269
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
270
|
+
// TOOL: memory_append
|
|
271
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
272
|
+
{
|
|
273
|
+
name: "memory_append",
|
|
274
|
+
description: `Adiciona uma entrada no final da sua memória com timestamp automático "## [YYYY-MM-DD HH:MM:SS]".
|
|
275
|
+
|
|
276
|
+
USE QUANDO APRENDER algo importante: padrões de código, bugs recorrentes, decisões arquiteturais, preferências do usuário, configurações importantes.
|
|
277
|
+
|
|
278
|
+
EXEMPLOS DE ENTRADAS VÁLIDAS:
|
|
279
|
+
- "Padrão: Este projeto usa App Router com estrutura /features/[domain]/"
|
|
280
|
+
- "Decisão: Escolhemos Zustand em vez de Redux porque é mais leve"
|
|
281
|
+
- "Bug: Firestore update falha silenciosamente quando array está vazio"
|
|
282
|
+
|
|
283
|
+
NÃO salve: Coisas triviais, informações temporárias, logs de conversa.
|
|
284
|
+
|
|
285
|
+
Parâmetro "agent": Seu nome de agent (opcional, padrão: "unknown").
|
|
286
|
+
Parâmetro "entry": OBRIGATÓRIO - Texto da informação a salvar.`,
|
|
287
|
+
inputSchema: MemoryAppendSchema,
|
|
288
|
+
},
|
|
289
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
290
|
+
// TOOL: memory_search
|
|
291
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
292
|
+
{
|
|
293
|
+
name: "memory_search",
|
|
294
|
+
description: `Busca um termo na sua memória sem precisar ler todo o conteúdo.
|
|
295
|
+
|
|
296
|
+
RETORNA: Até 20 ocorrências encontradas com número da linha. Busca case-insensitive.
|
|
297
|
+
|
|
298
|
+
EXEMPLOS DE BUSCA ÚTEIS:
|
|
299
|
+
- "Zod" → encontrar tudo sobre validação
|
|
300
|
+
- "bug" → encontrar bugs documentados
|
|
301
|
+
- "Firebase" → encontrar configurações
|
|
302
|
+
- "TypeScript" → encontrar padrões de tipagem
|
|
303
|
+
|
|
304
|
+
Se não encontrar, retorna mensagem de que nenhuma ocorrência foi encontrada.
|
|
305
|
+
|
|
306
|
+
Parâmetro "agent": Seu nome de agent (opcional, padrão: "unknown").
|
|
307
|
+
Parâmetro "query": OBRIGATÓRIO - Termo ou palavra-chave a buscar.`,
|
|
308
|
+
inputSchema: MemorySearchSchema,
|
|
309
|
+
},
|
|
310
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
311
|
+
// TOOL: memory_write
|
|
312
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
313
|
+
{
|
|
314
|
+
name: "memory_write",
|
|
315
|
+
description: `SUBSTITUI TODO o conteúdo da sua memória. APAGA tudo que estava antes - use com cautela.
|
|
316
|
+
|
|
317
|
+
USE QUANDO: Memória está grande (~150+ linhas) e precisa reorganizar, ou quer remover entradas obsoletas.
|
|
318
|
+
|
|
319
|
+
DICAS:
|
|
320
|
+
- Use "backup: true" para criar MEMORY.md.backup antes de sobrescrever
|
|
321
|
+
- Leia primeiro com memory_read para não perder conteúdo importante
|
|
322
|
+
- Organize em seções: ## Padrões, ## Bugs, ## Decisões, ## Configurações
|
|
323
|
+
|
|
324
|
+
EXEMPLO DE ESTRUTURA:
|
|
325
|
+
# Memória do Agent
|
|
326
|
+
|
|
327
|
+
## Padrões de Código
|
|
328
|
+
- Sempre use TypeScript estrito
|
|
329
|
+
|
|
330
|
+
## Bugs Conhecidos
|
|
331
|
+
- Bug XYZ: ocorre quando array vazio
|
|
332
|
+
Workaround: verificar length antes de usar
|
|
333
|
+
|
|
334
|
+
## Decisões
|
|
335
|
+
- Zustand em vez de Redux (mais leve)
|
|
336
|
+
|
|
337
|
+
Parâmetro "agent": Seu nome de agent (opcional, padrão: "unknown").
|
|
338
|
+
Parâmetro "content": OBRIGATÓRIO - Novo conteúdo completo em markdown.
|
|
339
|
+
Parâmetro "backup": Opcional (padrão: false) - Se true, cria backup antes de sobrescrever.`,
|
|
340
|
+
inputSchema: MemoryWriteSchema,
|
|
448
341
|
},
|
|
449
342
|
],
|
|
450
343
|
};
|
|
@@ -454,119 +347,56 @@ IMPORTANTE:
|
|
|
454
347
|
*/
|
|
455
348
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
456
349
|
const { name, arguments: args } = request.params;
|
|
457
|
-
if (name !== "memory") {
|
|
458
|
-
throw new Error(`Tool desconhecida: ${name}`);
|
|
459
|
-
}
|
|
460
|
-
const command = args?.command;
|
|
461
350
|
const agentName = args?.agent || "unknown";
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
351
|
+
try {
|
|
352
|
+
switch (name) {
|
|
353
|
+
case "memory_read": {
|
|
354
|
+
const parsed = MemoryReadSchema.safeParse(args);
|
|
355
|
+
if (!parsed.success) {
|
|
356
|
+
throw new Error(`Parâmetros inválidos: ${parsed.error.issues.map((e) => e.message).join(", ")}`);
|
|
357
|
+
}
|
|
358
|
+
const result = await handleRead(agentName);
|
|
359
|
+
return { content: [{ type: "text", text: result }] };
|
|
360
|
+
}
|
|
361
|
+
case "memory_append": {
|
|
362
|
+
const parsed = MemoryAppendSchema.safeParse(args);
|
|
363
|
+
if (!parsed.success) {
|
|
364
|
+
throw new Error(`Parâmetros inválidos: ${parsed.error.issues.map((e) => e.message).join(", ")}`);
|
|
365
|
+
}
|
|
366
|
+
const result = await handleAppend(agentName, parsed.data.entry);
|
|
367
|
+
return { content: [{ type: "text", text: result }] };
|
|
368
|
+
}
|
|
369
|
+
case "memory_search": {
|
|
370
|
+
const parsed = MemorySearchSchema.safeParse(args);
|
|
371
|
+
if (!parsed.success) {
|
|
372
|
+
throw new Error(`Parâmetros inválidos: ${parsed.error.issues.map((e) => e.message).join(", ")}`);
|
|
373
|
+
}
|
|
374
|
+
const result = await handleSearch(agentName, parsed.data.query);
|
|
375
|
+
return { content: [{ type: "text", text: result }] };
|
|
376
|
+
}
|
|
377
|
+
case "memory_write": {
|
|
378
|
+
const parsed = MemoryWriteSchema.safeParse(args);
|
|
379
|
+
if (!parsed.success) {
|
|
380
|
+
throw new Error(`Parâmetros inválidos: ${parsed.error.issues.map((e) => e.message).join(", ")}`);
|
|
381
|
+
}
|
|
382
|
+
const result = await handleWrite(agentName, parsed.data.content, parsed.data.backup);
|
|
383
|
+
return { content: [{ type: "text", text: result }] };
|
|
384
|
+
}
|
|
385
|
+
default:
|
|
386
|
+
throw new Error(`Tool desconhecida: ${name}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
465
391
|
return {
|
|
466
392
|
content: [
|
|
467
393
|
{
|
|
468
394
|
type: "text",
|
|
469
|
-
text: `❌
|
|
470
|
-
|
|
471
|
-
COMANDOS DISPONÍVEIS:
|
|
472
|
-
|
|
473
|
-
1. read - Lê a memória de um agent
|
|
474
|
-
2. write - Substitui todo o conteúdo da memória
|
|
475
|
-
3. append - Adiciona uma entrada ao final (com timestamp)
|
|
476
|
-
4. search - Busca um termo na memória
|
|
477
|
-
5. list - Lista todos os agents com memória no projeto
|
|
478
|
-
|
|
479
|
-
PARA MAIS DETALHES, CONSULTE A DESCRIÇÃO DA TOOL "memory"
|
|
480
|
-
`,
|
|
395
|
+
text: `❌ Erro ao executar tool "${name}": ${errorMessage}`,
|
|
481
396
|
},
|
|
482
397
|
],
|
|
483
398
|
};
|
|
484
399
|
}
|
|
485
|
-
// Executa comando específico
|
|
486
|
-
let result;
|
|
487
|
-
switch (command) {
|
|
488
|
-
case "read": {
|
|
489
|
-
result = await handleRead(agentName);
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
case "write": {
|
|
493
|
-
const content = args?.content;
|
|
494
|
-
if (!content) {
|
|
495
|
-
result = `❌ ERRO: O parâmetro "content" é OBRIGATÓRIO para o comando "write".
|
|
496
|
-
|
|
497
|
-
EXEMPLO DE USO CORRETO:
|
|
498
|
-
{
|
|
499
|
-
"command": "write",
|
|
500
|
-
"agent": "sentinel",
|
|
501
|
-
"content": "# Memória do Sentinel\\n\\n## Padrões\\n- Sempre use Zod para validação\\n\\n## Bugs\\n- Bug XYZ ocorre quando..."
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
DICA: Use "write" para reorganizar memória grande ou reconstruir do zero.
|
|
505
|
-
Para adicionar uma entrada preservando o histórico, use "append".
|
|
506
|
-
`;
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
result = await handleWrite(agentName, content);
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
case "append": {
|
|
513
|
-
const entry = args?.entry;
|
|
514
|
-
if (!entry) {
|
|
515
|
-
result = `❌ ERRO: O parâmetro "entry" é OBRIGATÓRIO para o comando "append".
|
|
516
|
-
|
|
517
|
-
EXEMPLO DE USO CORRETO:
|
|
518
|
-
{
|
|
519
|
-
"command": "append",
|
|
520
|
-
"agent": "sentinel",
|
|
521
|
-
"entry": "Padrão descoberto: Sempre use Zod para validar inputs do usuário em todos os componentes de formulário"
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
DICA: Use "append" para salvar aprendizados incrementais. O timestamp é adicionado automaticamente no formato:
|
|
525
|
-
## [2026-02-09 12:34:56]
|
|
526
|
-
Sua entrada aqui
|
|
527
|
-
|
|
528
|
-
Para salvar informações mais longas ou estruturadas, considere usar "write".
|
|
529
|
-
`;
|
|
530
|
-
break;
|
|
531
|
-
}
|
|
532
|
-
result = await handleAppend(agentName, entry);
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
case "search": {
|
|
536
|
-
const query = args?.query;
|
|
537
|
-
if (!query) {
|
|
538
|
-
result = `❌ ERRO: O parâmetro "query" é OBRIGATÓRIO para o comando "search".
|
|
539
|
-
|
|
540
|
-
EXEMPLO DE USO CORRETO:
|
|
541
|
-
{
|
|
542
|
-
"command": "search",
|
|
543
|
-
"agent": "sentinel",
|
|
544
|
-
"query": "Zod"
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
DICA: A busca é case-insensitive e retorna até 20 ocorrências com o número da linha.
|
|
548
|
-
Exemplos de busca úteis: "padrão", "bug", "TypeScript", "Firebase", "erro"
|
|
549
|
-
`;
|
|
550
|
-
break;
|
|
551
|
-
}
|
|
552
|
-
result = await handleSearch(agentName, query);
|
|
553
|
-
break;
|
|
554
|
-
}
|
|
555
|
-
case "list": {
|
|
556
|
-
result = await handleList();
|
|
557
|
-
break;
|
|
558
|
-
}
|
|
559
|
-
default:
|
|
560
|
-
result = `❌ Comando desconhecido: ${command}`;
|
|
561
|
-
}
|
|
562
|
-
return {
|
|
563
|
-
content: [
|
|
564
|
-
{
|
|
565
|
-
type: "text",
|
|
566
|
-
text: result,
|
|
567
|
-
},
|
|
568
|
-
],
|
|
569
|
-
};
|
|
570
400
|
});
|
|
571
401
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
572
402
|
// INICIALIZAÇÃO
|
|
@@ -581,34 +411,33 @@ async function main() {
|
|
|
581
411
|
}
|
|
582
412
|
// --help
|
|
583
413
|
if (args.includes("--help") || args.includes("-h")) {
|
|
584
|
-
console.log(`
|
|
585
|
-
@justmpm/memory - MCP Server para gerenciar memória persistente de subagents
|
|
586
|
-
|
|
587
|
-
Versão: ${PACKAGE_VERSION}
|
|
588
|
-
|
|
589
|
-
USO:
|
|
590
|
-
memory Inicia o servidor MCP (comunicação via stdio)
|
|
591
|
-
memory --version Mostra a versão do pacote
|
|
592
|
-
memory --help Mostra esta mensagem de ajuda
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
-
|
|
596
|
-
-
|
|
597
|
-
-
|
|
598
|
-
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
-
|
|
604
|
-
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
MIT © Koda AI Studio
|
|
414
|
+
console.log(`
|
|
415
|
+
@justmpm/memory - MCP Server para gerenciar memória persistente de subagents
|
|
416
|
+
|
|
417
|
+
Versão: ${PACKAGE_VERSION}
|
|
418
|
+
|
|
419
|
+
USO:
|
|
420
|
+
memory Inicia o servidor MCP (comunicação via stdio)
|
|
421
|
+
memory --version Mostra a versão do pacote
|
|
422
|
+
memory --help Mostra esta mensagem de ajuda
|
|
423
|
+
|
|
424
|
+
TOOLS MCP:
|
|
425
|
+
- memory_read Lê a memória de um agent
|
|
426
|
+
- memory_write Substitui toda a memória
|
|
427
|
+
- memory_append Adiciona uma entrada ao final
|
|
428
|
+
- memory_search Busca texto na memória
|
|
429
|
+
|
|
430
|
+
DOCUMENTAÇÃO:
|
|
431
|
+
Para mais detalhes, consulte:
|
|
432
|
+
- CLAUDE.md (Documentação para IAs)
|
|
433
|
+
- AGENTS.md (Guia para subagents)
|
|
434
|
+
- README.md (Documentação principal)
|
|
435
|
+
|
|
436
|
+
REPOSITÓRIO:
|
|
437
|
+
https://github.com/justmpm/memory-mcp
|
|
438
|
+
|
|
439
|
+
LICENÇA:
|
|
440
|
+
MIT © Koda AI Studio
|
|
612
441
|
`);
|
|
613
442
|
process.exit(0);
|
|
614
443
|
}
|