dd-harness-mcp 0.7.0 → 0.9.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.
- package/dist/cli/src/index.js +153 -52
- package/dist/mcp/src/index.js +33 -1
- package/package.json +40 -40
package/dist/cli/src/index.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { access } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
// DEP0190: Node imprime esse warning direto no stderr no instante em que
|
|
6
|
+
// `spawn(..., { shell: true })` recebe um array de args — de forma sincrona, ANTES de
|
|
7
|
+
// qualquer listener rodar, entao filtrar dentro de um `process.on("warning")` normal nao
|
|
8
|
+
// bloqueia a impressao (so o listener default e que imprime, e ele continua registrado
|
|
9
|
+
// junto do nosso). Por isso remover o listener default e a unica forma de suprimir.
|
|
10
|
+
// Real quando algum arg vem de fora, mas `instalaMcp` (mais abaixo) so passa literais
|
|
11
|
+
// fixos — sem isto o wizard de `start` mostrava um "DeprecationWarning" no meio do fluxo
|
|
12
|
+
// que parecia falha para quem esta vendo por dentro pela primeira vez.
|
|
13
|
+
process.removeAllListeners("warning");
|
|
5
14
|
import { termosDaConsulta } from "./argv.js";
|
|
6
15
|
import { check, status } from "./check.js";
|
|
7
16
|
import { CAMINHO_CONFIG, guardaConfigDaMaquina, guardaToken, leConfigDaMaquina, leConfigDoRepo, leToken, } from "./config.js";
|
|
@@ -24,61 +33,107 @@ import { subiuOWorker } from "./worker.js";
|
|
|
24
33
|
* em repositorio alheio tem que envelhecer bem, e cada dependencia e uma chance de nao
|
|
25
34
|
* envelhecer.
|
|
26
35
|
*/
|
|
27
|
-
const AJUDA = `dd-harness — a política e o Brain do projeto, no serviço
|
|
28
|
-
|
|
29
|
-
dd-harness start numa pasta vazia: conduz tudo (login,
|
|
30
|
-
espaço, projeto, config) numa tacada
|
|
31
|
-
dd-harness login --token <token> [--api <url>]
|
|
32
|
-
guarda a credencial desta máquina
|
|
33
|
-
dd-harness projeto <slug> --nome "<nome>" [--tenant <t>] [--api <url>]
|
|
34
|
-
cria o projeto no serviço (antes do init)
|
|
35
|
-
dd-harness init --tenant <t> --projeto <p> [--api <url>]
|
|
36
|
-
prepara o repositório (config + CLAUDE.md)
|
|
37
|
-
dd-harness pasta <slug> --definicao "o que entra e o que não entra"
|
|
38
|
-
cria a pasta que o gravar exige
|
|
39
|
-
dd-harness gravar <arquivo.md> registra uma memória a partir de um markdown
|
|
40
|
-
dd-harness editar <arquivo.md> corrige o que já está gravado
|
|
41
|
-
dd-harness arquivar <pasta>/<slug> --motivo <obsoleta|incorreta|fora_dos_filtros>
|
|
42
|
-
[--substituida-por <pasta>/<slug>]
|
|
43
|
-
tira de circulação sem apagar
|
|
44
|
-
dd-harness buscar "<pergunta>" acha memória por relevância, não por arquivo
|
|
45
|
-
dd-harness ler <pasta>/<slug> imprime a memória inteira, no formato de gravar
|
|
46
|
-
dd-harness reancorar <pasta>/<slug> --de "<alvo>" --para "<alvo>"
|
|
47
|
-
troca o alvo de uma âncora que mudou de lugar
|
|
48
|
-
dd-harness check [--commit <sha>] mede as âncoras e reporta a deriva
|
|
49
|
-
dd-harness status só lê: o tamanho do Brain e o que espera julgamento
|
|
50
|
-
dd-harness politica [--hook] imprime a política do serviço
|
|
51
|
-
saída 0 = veio; 3 = projeto sem política;
|
|
52
|
-
1 = não consegui buscar
|
|
53
|
-
--hook: fala o protocolo do SessionStart do
|
|
54
|
-
Claude Code, para pôr a política no contexto
|
|
55
|
-
dd-harness --help
|
|
56
|
-
dd-harness --version qual binário está instalado nesta máquina
|
|
57
|
-
|
|
58
|
-
Nada do dd-harness fica em disco: a política chega pelo hook de sessão, e a
|
|
59
|
-
memória pela busca, na hora.
|
|
36
|
+
const AJUDA = `dd-harness — a política e o Brain do projeto, no serviço
|
|
37
|
+
|
|
38
|
+
dd-harness start numa pasta vazia: conduz tudo (login,
|
|
39
|
+
espaço, projeto, config) numa tacada
|
|
40
|
+
dd-harness login --token <token> [--api <url>]
|
|
41
|
+
guarda a credencial desta máquina
|
|
42
|
+
dd-harness projeto <slug> --nome "<nome>" [--tenant <t>] [--api <url>]
|
|
43
|
+
cria o projeto no serviço (antes do init)
|
|
44
|
+
dd-harness init --tenant <t> --projeto <p> [--api <url>]
|
|
45
|
+
prepara o repositório (config + CLAUDE.md)
|
|
46
|
+
dd-harness pasta <slug> --definicao "o que entra e o que não entra"
|
|
47
|
+
cria a pasta que o gravar exige
|
|
48
|
+
dd-harness gravar <arquivo.md> registra uma memória a partir de um markdown
|
|
49
|
+
dd-harness editar <arquivo.md> corrige o que já está gravado
|
|
50
|
+
dd-harness arquivar <pasta>/<slug> --motivo <obsoleta|incorreta|fora_dos_filtros>
|
|
51
|
+
[--substituida-por <pasta>/<slug>]
|
|
52
|
+
tira de circulação sem apagar
|
|
53
|
+
dd-harness buscar "<pergunta>" acha memória por relevância, não por arquivo
|
|
54
|
+
dd-harness ler <pasta>/<slug> imprime a memória inteira, no formato de gravar
|
|
55
|
+
dd-harness reancorar <pasta>/<slug> --de "<alvo>" --para "<alvo>"
|
|
56
|
+
troca o alvo de uma âncora que mudou de lugar
|
|
57
|
+
dd-harness check [--commit <sha>] mede as âncoras e reporta a deriva
|
|
58
|
+
dd-harness status só lê: o tamanho do Brain e o que espera julgamento
|
|
59
|
+
dd-harness politica [--hook] imprime a política do serviço
|
|
60
|
+
saída 0 = veio; 3 = projeto sem política;
|
|
61
|
+
1 = não consegui buscar
|
|
62
|
+
--hook: fala o protocolo do SessionStart do
|
|
63
|
+
Claude Code, para pôr a política no contexto
|
|
64
|
+
dd-harness --help
|
|
65
|
+
dd-harness --version qual binário está instalado nesta máquina
|
|
66
|
+
|
|
67
|
+
Nada do dd-harness fica em disco: a política chega pelo hook de sessão, e a
|
|
68
|
+
memória pela busca, na hora.
|
|
60
69
|
`;
|
|
61
70
|
/**
|
|
62
71
|
* Os ganchos sao IMPRESSOS, nunca instalados. `.git/hooks` nao e versionado e nao e
|
|
63
72
|
* nosso: escrever la dentro sem a pessoa pedir e o mesmo tipo de invasao que
|
|
64
73
|
* sobrescrever o CLAUDE.md dela. Quem cola, decide.
|
|
65
74
|
*/
|
|
66
|
-
const GANCHOS = `
|
|
67
|
-
Opcional — o gancho que devolve a memória ao code review:
|
|
68
|
-
|
|
69
|
-
.git/hooks/post-commit (avisa quais memórias falam do que você mudou)
|
|
70
|
-
#!/bin/sh
|
|
71
|
-
dd-harness check --commit "$(git rev-parse HEAD)" || true
|
|
72
|
-
|
|
73
|
-
Termina em sucesso mesmo com deriva: avisa, não bloqueia.
|
|
74
|
-
|
|
75
|
-
O hook da política (\`dd-harness politica --hook\`) é outra coisa, e não é
|
|
75
|
+
const GANCHOS = `
|
|
76
|
+
Opcional — o gancho que devolve a memória ao code review:
|
|
77
|
+
|
|
78
|
+
.git/hooks/post-commit (avisa quais memórias falam do que você mudou)
|
|
79
|
+
#!/bin/sh
|
|
80
|
+
dd-harness check --commit "$(git rev-parse HEAD)" || true
|
|
81
|
+
|
|
82
|
+
Termina em sucesso mesmo com deriva: avisa, não bloqueia.
|
|
83
|
+
|
|
84
|
+
O hook da política (\`dd-harness politica --hook\`) é outra coisa, e não é
|
|
76
85
|
opcional — \`dd-harness init\` imprime a linha para o \`.claude/settings.json\`.`;
|
|
77
86
|
function argumento(argv, nome) {
|
|
78
87
|
const i = argv.indexOf(`--${nome}`);
|
|
79
88
|
return i >= 0 ? argv[i + 1] : undefined;
|
|
80
89
|
}
|
|
81
90
|
const API_PADRAO = "https://dd-harness.vercel.app";
|
|
91
|
+
/**
|
|
92
|
+
* Forca o `npx` a baixar e cachear `dd-harness-mcp` AGORA, dentro do wizard — nunca na
|
|
93
|
+
* primeira conexao do Claude Code. Sem isto, a primeira instalacao acontecia so quando
|
|
94
|
+
* o host tentava conectar ao servidor MCP, e o handshake tem timeout curto demais para
|
|
95
|
+
* esperar o download: a sessao real via `CONNECTION_CLOSED` em vez de "instalando".
|
|
96
|
+
*/
|
|
97
|
+
function instalaMcp() {
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
// stdio "inherit": o usuario ve o download do npx acontecendo (pode levar alguns
|
|
100
|
+
// segundos) e, se falhar, ve POR QUE — em vez do "nao consegui" mudo que nao dava
|
|
101
|
+
// pista nenhuma para diagnosticar. O DEP0190 que isto dispara e suprimido no topo
|
|
102
|
+
// do arquivo (`process.removeAllListeners("warning")`).
|
|
103
|
+
const p = spawn("npx", ["-y", "dd-harness-mcp", "--help"], {
|
|
104
|
+
shell: process.platform === "win32",
|
|
105
|
+
stdio: "inherit",
|
|
106
|
+
});
|
|
107
|
+
p.on("exit", (code) => resolve({ ok: code === 0, erro: code === 0 ? undefined : `código de saída ${code}` }));
|
|
108
|
+
p.on("error", (e) => resolve({ ok: false, erro: e.message }));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* `start` e o primeiro comando de quem esta chegando — rodar desatualizado aqui e o
|
|
113
|
+
* peor lugar para isso: foi assim que a pre-instalacao do MCP (esta mesma funcao,
|
|
114
|
+
* mais abaixo) ficou muda numa versao anterior que nao tinha essa etapa ainda.
|
|
115
|
+
* Falha de rede aqui nunca trava o wizard — so segue sem avisar.
|
|
116
|
+
*/
|
|
117
|
+
async function versaoDesatualizada() {
|
|
118
|
+
try {
|
|
119
|
+
const atual = await versao();
|
|
120
|
+
const controle = new AbortController();
|
|
121
|
+
const corte = setTimeout(() => controle.abort(), 3000);
|
|
122
|
+
const resp = await fetch("https://registry.npmjs.org/dd-harness/latest", {
|
|
123
|
+
signal: controle.signal,
|
|
124
|
+
});
|
|
125
|
+
clearTimeout(corte);
|
|
126
|
+
if (!resp.ok)
|
|
127
|
+
return null;
|
|
128
|
+
const { version: ultima } = (await resp.json());
|
|
129
|
+
if (!ultima || ultima === atual)
|
|
130
|
+
return null;
|
|
131
|
+
return { atual, ultima };
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
82
137
|
/**
|
|
83
138
|
* Tenta abrir o navegador padrao. Nunca lanca — falhar em abrir nao pode travar o
|
|
84
139
|
* wizard, so degrada para "aqui esta a URL, abra voce mesmo".
|
|
@@ -96,6 +151,10 @@ function tentaAbrirNavegador(url) {
|
|
|
96
151
|
// Segue sem navegador — a URL impressa antes desta chamada ja resolve.
|
|
97
152
|
}
|
|
98
153
|
}
|
|
154
|
+
/** Token no terminal aparece mascarado: o prefixo basta para reconhecer, o segredo nao precisa ser lido em voz alta. */
|
|
155
|
+
function mascara(token) {
|
|
156
|
+
return token.length <= 16 ? "***" : `${token.slice(0, 12)}...${token.slice(-4)}`;
|
|
157
|
+
}
|
|
99
158
|
/**
|
|
100
159
|
* `dd-harness start` — o wizard para pasta vazia.
|
|
101
160
|
*
|
|
@@ -120,14 +179,37 @@ async function comandoStart() {
|
|
|
120
179
|
// ENOENT: exatamente o caso esperado, segue.
|
|
121
180
|
}
|
|
122
181
|
console.log("Iniciando o dd-harness nesta pasta.\n");
|
|
182
|
+
// 0. Versao. `start` e o comando de bootstrap: rodar velho aqui significa perder
|
|
183
|
+
// correcoes deste proprio wizard sem nenhum aviso (foi o que aconteceu com a
|
|
184
|
+
// pre-instalacao do MCP, passo 5.5 abaixo, numa versao anterior a ela existir).
|
|
185
|
+
const desatualizado = await versaoDesatualizada();
|
|
186
|
+
if (desatualizado) {
|
|
187
|
+
console.log(`AVISO: você está na versão ${desatualizado.atual}, e a mais recente é ` +
|
|
188
|
+
`${desatualizado.ultima}. Rode \`npm install -g dd-harness@latest\` e comece de ` +
|
|
189
|
+
"novo — start segue mesmo assim, mas pode faltar correção.\n");
|
|
190
|
+
}
|
|
123
191
|
// 1. Credencial. Sem ela nada do resto e possivel — nem listar tenant.
|
|
192
|
+
// O estado aparece SEMPRE, mesmo quando ja existe credencial: antes o passo era
|
|
193
|
+
// pulado em silencio, e quem rodava `start` com um token velho (ou de outra conta)
|
|
194
|
+
// nao tinha como perceber — o wizard so falhava depois, ao listar espacos.
|
|
124
195
|
let token = await leToken(API_PADRAO);
|
|
196
|
+
if (token) {
|
|
197
|
+
console.log(`Credencial: ${mascara(token)} (${API_PADRAO})`);
|
|
198
|
+
const troca = await pergunta("Usar esta credencial? [S/n]: ");
|
|
199
|
+
if (/^n/i.test(troca))
|
|
200
|
+
token = null;
|
|
201
|
+
}
|
|
125
202
|
if (!token) {
|
|
126
|
-
|
|
127
|
-
|
|
203
|
+
const url = `${API_PADRAO}/tokens`;
|
|
204
|
+
console.log(`\nCrie um token pessoal em ${url} — abrindo no navegador...`);
|
|
205
|
+
tentaAbrirNavegador(url);
|
|
206
|
+
token = await pergunta("Cole o token aqui: ");
|
|
207
|
+
if (!token)
|
|
208
|
+
throw new Error("sem token não dá para seguir: `start` fala com o serviço em todos os passos.");
|
|
128
209
|
await guardaToken(API_PADRAO, token);
|
|
129
|
-
console.log("Credencial guardada
|
|
210
|
+
console.log("Credencial guardada.");
|
|
130
211
|
}
|
|
212
|
+
console.log("");
|
|
131
213
|
// 2. Espaco (tenant). Criar um e ato de dono — nunca por aqui — mas ESCOLHER entre
|
|
132
214
|
// os que ja existem e so leitura, e e o que faltava para nao exigir o slug de memoria.
|
|
133
215
|
let tenants = await listaTenants(API_PADRAO, token);
|
|
@@ -139,18 +221,28 @@ async function comandoStart() {
|
|
|
139
221
|
tenants = await listaTenants(API_PADRAO, token);
|
|
140
222
|
}
|
|
141
223
|
const tenant = await escolha("\nEscolha um espaço:", tenants.map((t) => ({ rotulo: `${t.nome} (${t.slug})`, valor: t.slug })));
|
|
142
|
-
// 3. Projeto. Criar e subordinado a estar num espaco
|
|
143
|
-
|
|
224
|
+
// 3. Projeto. Criar e subordinado a estar num espaco - isso o CLI ja faz sozinho.
|
|
225
|
+
// A pasta se chama `tiktok-drawer`; o projeto se chama `TikTok Drawer`. Sugerir o
|
|
226
|
+
// nome da pasta cru fazia o wizard propor um identificador onde se pede um titulo —
|
|
227
|
+
// e o slug, que e quem precisa daquele formato, ja sai daqui de baixo sozinho.
|
|
228
|
+
const pasta = process.cwd().split(/[\\/]/).pop() ?? "meu-projeto";
|
|
229
|
+
const nomeSugerido = pasta
|
|
230
|
+
.replace(/[-_]+/g, " ")
|
|
231
|
+
.replace(/\s+/g, " ")
|
|
232
|
+
.trim()
|
|
233
|
+
.replace(/\b\w/g, (c) => c.toUpperCase()) || "Meu Projeto";
|
|
144
234
|
const nome = (await pergunta(`\nNome do projeto [${nomeSugerido}]: `)) || nomeSugerido;
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
|
|
235
|
+
// O slug sai do nome, sem perguntar: e identificador, nao escolha editorial, e quem
|
|
236
|
+
// esta comecando nao tem como saber que ele vira a chave do `.dd-harness.json`.
|
|
237
|
+
// Nome so com caracteres especiais (ex: "!!!") normaliza para string vazia - o
|
|
238
|
+
// fallback evita slug vazio, que o servidor recusaria com erro confuso.
|
|
239
|
+
const slugDoProjeto = nome
|
|
148
240
|
.toLowerCase()
|
|
149
241
|
.normalize("NFD")
|
|
150
242
|
.replace(/[̀-ͯ]/g, "")
|
|
151
243
|
.replace(/[^a-z0-9]+/g, "-")
|
|
152
244
|
.replace(/^-+|-+$/g, "") || "meu-projeto";
|
|
153
|
-
|
|
245
|
+
console.log(`Identificador: ${slugDoProjeto}`);
|
|
154
246
|
const resultadoProjeto = await criaProjeto(process.cwd(), slugDoProjeto, nome, {
|
|
155
247
|
tenant,
|
|
156
248
|
api: API_PADRAO,
|
|
@@ -186,6 +278,15 @@ async function comandoStart() {
|
|
|
186
278
|
acrescentado: "atualizado .mcp.json (servidor adicionado ao que já existia)",
|
|
187
279
|
}[mcp.estado]);
|
|
188
280
|
}
|
|
281
|
+
if (mcp.ok) {
|
|
282
|
+
console.log("\nInstalando o servidor dd-harness-mcp (primeira vez pode demorar um pouco)...");
|
|
283
|
+
const { ok: instalou, erro: erroInstalacao } = await instalaMcp();
|
|
284
|
+
console.log(instalou
|
|
285
|
+
? "dd-harness-mcp instalado — a próxima sessão do Claude Code conecta na hora."
|
|
286
|
+
: `AVISO: não consegui pré-instalar dd-harness-mcp (${erroInstalacao}). A primeira ` +
|
|
287
|
+
"conexão do Claude Code pode demorar ou falhar; se falhar, abra uma nova sessão " +
|
|
288
|
+
"e tente de novo.");
|
|
289
|
+
}
|
|
189
290
|
// 6. AGENTS.md — so quem usa outra ferramenta alem do Claude Code precisa.
|
|
190
291
|
const outraFerramenta = await pergunta("\nVai abrir este projeto em Codex, Cursor ou outra ferramenta além do Claude " +
|
|
191
292
|
"Code? [s/N]: ");
|
package/dist/mcp/src/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
3
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
3
4
|
import * as z from "zod/v4";
|
|
@@ -293,4 +294,35 @@ Conteúdo vazio é válido e significa apagar o artefato.`,
|
|
|
293
294
|
});
|
|
294
295
|
return server;
|
|
295
296
|
}
|
|
296
|
-
|
|
297
|
+
/**
|
|
298
|
+
* `--help` / `--version` respondem e SAEM. Sem isto, qualquer invocacao com argumento
|
|
299
|
+
* caia no `serveStdio` e ficava esperando stdin para sempre — e foi assim que o
|
|
300
|
+
* aquecedor de cache do `dd-harness start` (que chamava `npx -y dd-harness-mcp --help`
|
|
301
|
+
* so para forcar o download) travou o wizard inteiro depois que o shebang passou a
|
|
302
|
+
* deixar o servidor subir de verdade.
|
|
303
|
+
*/
|
|
304
|
+
const args = process.argv.slice(2);
|
|
305
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
306
|
+
console.log(`dd-harness-mcp — servidor MCP do dd-harness (fala por stdio, nao por terminal)
|
|
307
|
+
|
|
308
|
+
Nao se roda a mao: quem o inicia e o host MCP (Claude Code, Codex, Cursor), pela
|
|
309
|
+
declaracao em \`.mcp.json\`. Sem um host do outro lado ele fica esperando mensagem
|
|
310
|
+
no stdin, que e o comportamento correto de um servidor stdio.
|
|
311
|
+
|
|
312
|
+
--help esta mensagem
|
|
313
|
+
--version a versao instalada
|
|
314
|
+
|
|
315
|
+
Para declarar no seu repositorio, rode \`dd-harness start\`.`);
|
|
316
|
+
}
|
|
317
|
+
else if (args.includes("--version") || args.includes("-V")) {
|
|
318
|
+
const { readFile } = await import("node:fs/promises");
|
|
319
|
+
const { fileURLToPath } = await import("node:url");
|
|
320
|
+
const { dirname, join } = await import("node:path");
|
|
321
|
+
// `dist/mcp/src/index.js` -> tres niveis ate a raiz do pacote.
|
|
322
|
+
const aqui = dirname(fileURLToPath(import.meta.url));
|
|
323
|
+
const lido = await readFile(join(aqui, "..", "..", "..", "package.json"), "utf8");
|
|
324
|
+
console.log(JSON.parse(lido).version ?? "desconhecida");
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
serveStdio(criaServidor);
|
|
328
|
+
}
|
package/package.json
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dd-harness-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "Servidor MCP do dd-harness: o agente consulta e grava memoria como ferramenta, sem passar por arquivo.",
|
|
6
|
-
"license": "UNLICENSED",
|
|
7
|
-
"author": "Diego Dias",
|
|
8
|
-
"keywords": [
|
|
9
|
-
"claude-code",
|
|
10
|
-
"mcp",
|
|
11
|
-
"model-context-protocol",
|
|
12
|
-
"ai-agents",
|
|
13
|
-
"memory"
|
|
14
|
-
],
|
|
15
|
-
"homepage": "https://dd-harness.vercel.app",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/diegodias93/dd-harness-online.git",
|
|
19
|
-
"directory": "packages/mcp"
|
|
20
|
-
},
|
|
21
|
-
"//bin": "`dist/mcp/src/` e nao `dist/` porque o build abrange dois diretorios (este pacote e o fonte do CLI), e o `rootDir` comum e `packages/`. Conferir com `node dist/mcp/src/index.js`
|
|
22
|
-
"bin": {
|
|
23
|
-
"dd-harness-mcp": "dist/mcp/src/index.js"
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist"
|
|
27
|
-
],
|
|
28
|
-
"engines": {
|
|
29
|
-
"node": ">=20"
|
|
30
|
-
},
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@modelcontextprotocol/server": "^2.0.0",
|
|
33
|
-
"zod": "^4.5.4"
|
|
34
|
-
},
|
|
35
|
-
"scripts": {
|
|
36
|
-
"typecheck": "tsc -p . --noEmit",
|
|
37
|
-
"build": "tsc -p tsconfig.build.json",
|
|
38
|
-
"prepublishOnly": "npm run build"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dd-harness-mcp",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Servidor MCP do dd-harness: o agente consulta e grava memoria como ferramenta, sem passar por arquivo.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"author": "Diego Dias",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"claude-code",
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"memory"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://dd-harness.vercel.app",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/diegodias93/dd-harness-online.git",
|
|
19
|
+
"directory": "packages/mcp"
|
|
20
|
+
},
|
|
21
|
+
"//bin": "`dist/mcp/src/` e nao `dist/` porque o build abrange dois diretorios (este pacote e o fonte do CLI), e o `rootDir` comum e `packages/`. Conferir com `npx -y dd-harness-mcp` numa cache limpa antes de publicar — NAO com `node dist/mcp/src/index.js`: rodar pelo caminho direto passa mesmo quando o pacote instalado esta quebrado, porque o defeito mora no shim que o npm gera. Sem o shebang em `src/index.ts` o shim `.cmd` do Windows chama o `.js` sem `node` na frente, e o servidor morre limpo (exit 0, em silencio) antes do handshake — o cliente so ve CONNECTION_CLOSED.",
|
|
22
|
+
"bin": {
|
|
23
|
+
"dd-harness-mcp": "dist/mcp/src/index.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
33
|
+
"zod": "^4.5.4"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"typecheck": "tsc -p . --noEmit",
|
|
37
|
+
"build": "tsc -p tsconfig.build.json",
|
|
38
|
+
"prepublishOnly": "npm run build"
|
|
39
|
+
}
|
|
40
|
+
}
|