@haema/cli 0.8.1
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/README.md +258 -0
- package/dist/auth.js +30 -0
- package/dist/auth.js.map +1 -0
- package/dist/discoverClaudeFiles.js +132 -0
- package/dist/discoverClaudeFiles.js.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/install.js +353 -0
- package/dist/mcp/install.js.map +1 -0
- package/dist/mcp/mcpClient.js +55 -0
- package/dist/mcp/mcpClient.js.map +1 -0
- package/dist/mcp/resolveProjectId.js +27 -0
- package/dist/mcp/resolveProjectId.js.map +1 -0
- package/dist/mcp/server.js +344 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/addTask.js +15 -0
- package/dist/mcp/tools/addTask.js.map +1 -0
- package/dist/mcp/tools/applyHooks.js +110 -0
- package/dist/mcp/tools/applyHooks.js.map +1 -0
- package/dist/mcp/tools/brief.js +166 -0
- package/dist/mcp/tools/brief.js.map +1 -0
- package/dist/mcp/tools/createFolder.js +11 -0
- package/dist/mcp/tools/createFolder.js.map +1 -0
- package/dist/mcp/tools/finishTask.js +16 -0
- package/dist/mcp/tools/finishTask.js.map +1 -0
- package/dist/mcp/tools/getTask.js +31 -0
- package/dist/mcp/tools/getTask.js.map +1 -0
- package/dist/mcp/tools/listTasks.js +27 -0
- package/dist/mcp/tools/listTasks.js.map +1 -0
- package/dist/mcp/tools/loadSkill.js +8 -0
- package/dist/mcp/tools/loadSkill.js.map +1 -0
- package/dist/mcp/tools/logSession.js +13 -0
- package/dist/mcp/tools/logSession.js.map +1 -0
- package/dist/mcp/tools/recall.js +23 -0
- package/dist/mcp/tools/recall.js.map +1 -0
- package/dist/mcp/tools/signin.js +111 -0
- package/dist/mcp/tools/signin.js.map +1 -0
- package/dist/mcp/tools/signout.js +11 -0
- package/dist/mcp/tools/signout.js.map +1 -0
- package/dist/mcp/tools/startTask.js +21 -0
- package/dist/mcp/tools/startTask.js.map +1 -0
- package/dist/mcp/tools/updateTask.js +9 -0
- package/dist/mcp/tools/updateTask.js.map +1 -0
- package/dist/mcp/tools/uploadPrompt.js +32 -0
- package/dist/mcp/tools/uploadPrompt.js.map +1 -0
- package/dist/mcp/tools/whoami.js +13 -0
- package/dist/mcp/tools/whoami.js.map +1 -0
- package/dist/openBrowser.js +15 -0
- package/dist/openBrowser.js.map +1 -0
- package/dist/readClaudeFile.js +16 -0
- package/dist/readClaudeFile.js.map +1 -0
- package/dist/scanLimits.js +15 -0
- package/dist/scanLimits.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { resolveOrInitProject, resolveProject } from "./resolveProjectId.js";
|
|
7
|
+
import { handleAddTask } from "./tools/addTask.js";
|
|
8
|
+
import { handleApplyHooks } from "./tools/applyHooks.js";
|
|
9
|
+
import { handleBrief } from "./tools/brief.js";
|
|
10
|
+
import { handleCreateFolder } from "./tools/createFolder.js";
|
|
11
|
+
import { handleGetTask } from "./tools/getTask.js";
|
|
12
|
+
import { handleFinishTask } from "./tools/finishTask.js";
|
|
13
|
+
import { handleListTasks } from "./tools/listTasks.js";
|
|
14
|
+
import { handleLoadSkill } from "./tools/loadSkill.js";
|
|
15
|
+
import { handleRecall } from "./tools/recall.js";
|
|
16
|
+
import { handleSignin } from "./tools/signin.js";
|
|
17
|
+
import { handleSignout } from "./tools/signout.js";
|
|
18
|
+
import { handleStartTask } from "./tools/startTask.js";
|
|
19
|
+
import { handleUpdateTask } from "./tools/updateTask.js";
|
|
20
|
+
import { handleUploadPrompt } from "./tools/uploadPrompt.js";
|
|
21
|
+
import { handleWhoami } from "./tools/whoami.js";
|
|
22
|
+
// 모든 일반 tool에 공통으로 붙는 optional cwd 파라미터
|
|
23
|
+
const cwdParam = {
|
|
24
|
+
cwd: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("프로젝트 절대경로 (생략 시 서버 시작 디렉토리의 프로젝트 사용). " +
|
|
28
|
+
"여러 프로젝트를 넘나들 때 명시해요."),
|
|
29
|
+
};
|
|
30
|
+
function createServer(config, startCwd) {
|
|
31
|
+
const server = new McpServer({ name: "haema-memory", version: "1.0.0" });
|
|
32
|
+
// 서버 시작 cwd 기준 projectId를 첫 툴 호출 시점에 한 번만 resolve (lazy).
|
|
33
|
+
// undefined = 아직 조회 안 함, null = 조회했으나 미등록 프로젝트
|
|
34
|
+
let defaultProjectId = undefined;
|
|
35
|
+
async function getDefaultPid() {
|
|
36
|
+
if (defaultProjectId === undefined) {
|
|
37
|
+
defaultProjectId = await resolveOrInitProject(startCwd, config);
|
|
38
|
+
}
|
|
39
|
+
return defaultProjectId;
|
|
40
|
+
}
|
|
41
|
+
const NOT_REGISTERED = {
|
|
42
|
+
content: [{
|
|
43
|
+
type: "text",
|
|
44
|
+
text: "Haema 프로젝트를 찾을 수 없어요. `signin` 툴로 로그인 상태를 확인해 주세요.",
|
|
45
|
+
}],
|
|
46
|
+
};
|
|
47
|
+
const NOT_LOGGED_IN = {
|
|
48
|
+
content: [{
|
|
49
|
+
type: "text",
|
|
50
|
+
text: "로그인이 필요해요. `signin` 툴로 먼저 로그인해 주세요.",
|
|
51
|
+
}],
|
|
52
|
+
};
|
|
53
|
+
server.tool("brief", "세션 시작 브리핑. 현재 상태, AI 추천 태스크, 행동 지침을 반환해요. 응답 하단의 지침 섹션을 반드시 따르세요.", cwdParam, async (args) => {
|
|
54
|
+
if (!config)
|
|
55
|
+
return NOT_LOGGED_IN;
|
|
56
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
57
|
+
if (!pid)
|
|
58
|
+
return NOT_REGISTERED;
|
|
59
|
+
return { content: [{ type: "text", text: await handleBrief(pid, config) }] };
|
|
60
|
+
});
|
|
61
|
+
server.tool("recall", "의미 유사도로 과거 생각을 검색해요.", {
|
|
62
|
+
...cwdParam,
|
|
63
|
+
query: z.string().describe("검색 쿼리"),
|
|
64
|
+
limit: z.number().int().min(1).max(50).optional().describe("최대 결과 수 (기본 10)"),
|
|
65
|
+
}, async (args) => {
|
|
66
|
+
if (!config)
|
|
67
|
+
return NOT_LOGGED_IN;
|
|
68
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
69
|
+
if (!pid)
|
|
70
|
+
return NOT_REGISTERED;
|
|
71
|
+
return { content: [{ type: "text", text: await handleRecall(args, pid, config) }] };
|
|
72
|
+
});
|
|
73
|
+
server.tool("add_task", "새 태스크를 추가해요. 유저 작업 요청 시 코드 작업 전에 반드시 먼저 호출하세요. 등록 직후 update_task로 IN_PROGRESS 변경.", {
|
|
74
|
+
...cwdParam,
|
|
75
|
+
title: z.string().describe("태스크 제목"),
|
|
76
|
+
description: z.string().optional().describe("상세 설명"),
|
|
77
|
+
module: z.string().optional().describe("모듈 슬러그. backend · frontend · database · designer · integration · devops · planner · testing 중 선택 (스킬 자동 매칭에 사용됨)"),
|
|
78
|
+
priority: z.number().int().min(0).max(10).optional().describe("우선순위 0-10 (기본 0)"),
|
|
79
|
+
folderId: z.string().optional().describe("폴더 ID (brief의 폴더 목록에서 확인)"),
|
|
80
|
+
}, async (args) => {
|
|
81
|
+
if (!config)
|
|
82
|
+
return NOT_LOGGED_IN;
|
|
83
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
84
|
+
if (!pid)
|
|
85
|
+
return NOT_REGISTERED;
|
|
86
|
+
return { content: [{ type: "text", text: await handleAddTask(args, pid, config) }] };
|
|
87
|
+
});
|
|
88
|
+
server.tool("start_task", "태스크를 생성하고 즉시 IN_PROGRESS로 시작해요. add_task + update_task(IN_PROGRESS) 두 번 호출을 한 번으로 줄여요.", {
|
|
89
|
+
...cwdParam,
|
|
90
|
+
title: z.string().describe("태스크 제목"),
|
|
91
|
+
description: z.string().optional().describe("상세 설명"),
|
|
92
|
+
module: z.string().optional().describe("모듈 슬러그. backend · frontend · database · designer · integration · devops · planner · testing 중 선택 (스킬 자동 매칭에 사용됨)"),
|
|
93
|
+
priority: z.number().int().min(0).max(10).optional().describe("우선순위 0-10 (기본 0)"),
|
|
94
|
+
folderId: z.string().optional().describe("폴더 ID (brief의 폴더 목록에서 확인)"),
|
|
95
|
+
}, async (args) => {
|
|
96
|
+
if (!config)
|
|
97
|
+
return NOT_LOGGED_IN;
|
|
98
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
99
|
+
if (!pid)
|
|
100
|
+
return NOT_REGISTERED;
|
|
101
|
+
return { content: [{ type: "text", text: await handleStartTask(args, pid, config) }] };
|
|
102
|
+
});
|
|
103
|
+
server.tool("finish_task", "태스크를 DONE으로 완료해요. keyDecisions에는 이 태스크에서 내린 핵심 결정/인사이트를 추출해서 전달하세요 — 아키텍처 선택, 버그 원인, 방향 변경 등 다음 세션에서 recall로 찾을 만한 내용만. 단순 구현 작업은 생략.", {
|
|
104
|
+
...cwdParam,
|
|
105
|
+
taskSeq: z.number().int().positive().describe("완료할 태스크 번호 (예: 1, 42)"),
|
|
106
|
+
summary: z.string().describe("이번 세션에서 한 작업 요약 (2-5문장)"),
|
|
107
|
+
aiTool: z
|
|
108
|
+
.enum(["claude", "cursor", "gemini", "codex"])
|
|
109
|
+
.optional()
|
|
110
|
+
.describe("사용 중인 AI 도구 (생략 시 unknown)"),
|
|
111
|
+
keyDecisions: z
|
|
112
|
+
.array(z.string())
|
|
113
|
+
.optional()
|
|
114
|
+
.describe("이 태스크의 핵심 결정/인사이트 목록. recall 검색 대상이 됨."),
|
|
115
|
+
outcome: z
|
|
116
|
+
.string()
|
|
117
|
+
.optional()
|
|
118
|
+
.describe("실제로 무엇을 구현/변경했는지 자유 서술 (2-5문장). 다음 세션에서 이 태스크 결과를 빠르게 파악하는 데 쓰임."),
|
|
119
|
+
}, async (args) => {
|
|
120
|
+
if (!config)
|
|
121
|
+
return NOT_LOGGED_IN;
|
|
122
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
123
|
+
if (!pid)
|
|
124
|
+
return NOT_REGISTERED;
|
|
125
|
+
return { content: [{ type: "text", text: await handleFinishTask(args, pid, config) }] };
|
|
126
|
+
});
|
|
127
|
+
server.tool("update_task", "태스크 상태나 내용을 업데이트해요. taskSeq 는 list_tasks 나 brief 에서 표시되는 #번호예요. 작업 시작 시 IN_PROGRESS, 완료 시 DONE으로 반드시 업데이트하세요.", {
|
|
128
|
+
...cwdParam,
|
|
129
|
+
taskSeq: z.number().int().positive().describe("태스크 번호 (예: 1, 42)"),
|
|
130
|
+
status: z.enum(["PENDING", "IN_PROGRESS", "DONE", "CANCELLED"]).optional().describe("새 상태"),
|
|
131
|
+
title: z.string().optional().describe("새 제목"),
|
|
132
|
+
description: z.string().optional().describe("새 설명"),
|
|
133
|
+
module: z.string().optional().describe("새 모듈명"),
|
|
134
|
+
priority: z.number().int().min(0).max(10).optional().describe("새 우선순위"),
|
|
135
|
+
}, async (args) => {
|
|
136
|
+
if (!config)
|
|
137
|
+
return NOT_LOGGED_IN;
|
|
138
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
139
|
+
if (!pid)
|
|
140
|
+
return NOT_REGISTERED;
|
|
141
|
+
return { content: [{ type: "text", text: await handleUpdateTask({ ...args, projectId: pid }, config) }] };
|
|
142
|
+
});
|
|
143
|
+
server.tool("load_skill", "상황에 맞는 스킬의 전체 지침을 로드해요. brief 응답에 listed된 사용 가능한 스킬을 맥락에 맞게 호출하세요.", {
|
|
144
|
+
...cwdParam,
|
|
145
|
+
slug: z.string().describe("스킬 슬러그 (예: planner, reviewer)"),
|
|
146
|
+
}, async (args) => {
|
|
147
|
+
if (!config)
|
|
148
|
+
return NOT_LOGGED_IN;
|
|
149
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
150
|
+
if (!pid)
|
|
151
|
+
return NOT_REGISTERED;
|
|
152
|
+
return { content: [{ type: "text", text: await handleLoadSkill(args, pid, config) }] };
|
|
153
|
+
});
|
|
154
|
+
server.tool("propose_skill", "이 프로젝트에 커스텀 스킬을 등록해요. 반복 패턴을 3번 이상 작업했을 때 스킬로 저장하면 다음 세션에서 load_skill로 바로 불러올 수 있어요.", {
|
|
155
|
+
...cwdParam,
|
|
156
|
+
name: z.string().describe("스킬 이름 (예: '타입스크립트 마이그레이션')"),
|
|
157
|
+
description: z.string().describe("한 줄 설명"),
|
|
158
|
+
folder: z.string().describe("스킬 그룹 폴더명 (예: 리팩토링, 테스트, 배포)"),
|
|
159
|
+
content: z.string().describe("에이전트가 따를 마크다운 지침 전문"),
|
|
160
|
+
patternSummary: z.string().optional().describe("이 패턴이 필요하다고 판단한 근거"),
|
|
161
|
+
contextHint: z.string().describe("이 스킬을 사용해야 하는 상황 (예: 외부 API 연동 태스크 시작 전에 사용)"),
|
|
162
|
+
}, async (args) => {
|
|
163
|
+
if (!config)
|
|
164
|
+
return NOT_LOGGED_IN;
|
|
165
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
166
|
+
if (!pid)
|
|
167
|
+
return NOT_REGISTERED;
|
|
168
|
+
const res = await fetch(`${config.appUrl}/api/memory/custom-skills`, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${config.apiKey}` },
|
|
171
|
+
body: JSON.stringify({
|
|
172
|
+
projectId: pid,
|
|
173
|
+
name: args.name,
|
|
174
|
+
description: args.description,
|
|
175
|
+
folder: args.folder,
|
|
176
|
+
content: args.content,
|
|
177
|
+
patternSummary: args.patternSummary,
|
|
178
|
+
contextHint: args.contextHint,
|
|
179
|
+
}),
|
|
180
|
+
signal: AbortSignal.timeout(10_000),
|
|
181
|
+
});
|
|
182
|
+
const data = await res.json();
|
|
183
|
+
if (!data.ok)
|
|
184
|
+
return { content: [{ type: "text", text: `오류: ${data.error}` }] };
|
|
185
|
+
return {
|
|
186
|
+
content: [{
|
|
187
|
+
type: "text",
|
|
188
|
+
text: `스킬 등록 완료: "${data.skill.name}" (슬러그: ${data.skill.slug})\n다음 세션부터 load_skill(slug="${data.skill.slug}")로 불러올 수 있어요.`,
|
|
189
|
+
}],
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
server.tool("task_detail", "태스크 하나의 전체 상세 정보를 조회해요. title, description, status, module, outcome, keyDecisions 등을 반환해요.", {
|
|
193
|
+
...cwdParam,
|
|
194
|
+
taskSeq: z.number().int().positive().describe("태스크 번호 (예: 1, 42)"),
|
|
195
|
+
}, async (args) => {
|
|
196
|
+
if (!config)
|
|
197
|
+
return NOT_LOGGED_IN;
|
|
198
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
199
|
+
if (!pid)
|
|
200
|
+
return NOT_REGISTERED;
|
|
201
|
+
return { content: [{ type: "text", text: await handleGetTask(args, pid, config) }] };
|
|
202
|
+
});
|
|
203
|
+
server.tool("list_tasks", "태스크 목록을 봐요. status 와 module 로 필터링 가능.", {
|
|
204
|
+
...cwdParam,
|
|
205
|
+
status: z
|
|
206
|
+
.enum(["PENDING", "IN_PROGRESS", "DONE", "CANCELLED"])
|
|
207
|
+
.optional()
|
|
208
|
+
.describe("상태 필터"),
|
|
209
|
+
module: z.string().optional().describe("모듈 필터 (예: auth)"),
|
|
210
|
+
}, async (args) => {
|
|
211
|
+
if (!config)
|
|
212
|
+
return NOT_LOGGED_IN;
|
|
213
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
214
|
+
if (!pid)
|
|
215
|
+
return NOT_REGISTERED;
|
|
216
|
+
return { content: [{ type: "text", text: await handleListTasks(args, pid, config) }] };
|
|
217
|
+
});
|
|
218
|
+
server.tool("pin_task", "태스크를 장기 기억(LONG_TERM)으로 고정해요. AI 자동 감쇠 대상에서 영구 제외되며 brief에 항상 표시됩니다.", {
|
|
219
|
+
...cwdParam,
|
|
220
|
+
taskSeq: z.number().int().positive().describe("고정할 태스크 번호 (예: 1, 42)"),
|
|
221
|
+
pin: z.boolean().optional().describe("true=고정, false=고정 해제 (기본값 true)"),
|
|
222
|
+
}, async (args) => {
|
|
223
|
+
if (!config)
|
|
224
|
+
return NOT_LOGGED_IN;
|
|
225
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
226
|
+
if (!pid)
|
|
227
|
+
return NOT_REGISTERED;
|
|
228
|
+
const isPinned = args.pin !== false;
|
|
229
|
+
const res = await fetch(`${config.appUrl}/api/memory/tasks/${args.taskSeq}`, {
|
|
230
|
+
method: "PATCH",
|
|
231
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${config.apiKey}` },
|
|
232
|
+
body: JSON.stringify({ projectId: pid, isPinned }),
|
|
233
|
+
});
|
|
234
|
+
const data = await res.json();
|
|
235
|
+
if (!data.ok)
|
|
236
|
+
return { content: [{ type: "text", text: `오류: ${data.error}` }] };
|
|
237
|
+
return {
|
|
238
|
+
content: [{
|
|
239
|
+
type: "text",
|
|
240
|
+
text: isPinned
|
|
241
|
+
? `#${args.taskSeq} 태스크를 장기 기억으로 고정했어요. AI 감쇠 대상에서 제외됩니다.`
|
|
242
|
+
: `#${args.taskSeq} 태스크의 장기 기억 고정을 해제했어요.`,
|
|
243
|
+
}],
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
server.tool("get_insights", "최근 AI 메모리 분석 인사이트를 조회해요. 프로젝트 패턴, 위험 요소, 추천 태스크를 포함해요.", {
|
|
247
|
+
...cwdParam,
|
|
248
|
+
limit: z.number().int().min(1).max(10).optional().describe("최대 reflection 수 (기본 3)"),
|
|
249
|
+
}, async (args) => {
|
|
250
|
+
if (!config)
|
|
251
|
+
return NOT_LOGGED_IN;
|
|
252
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
253
|
+
if (!pid)
|
|
254
|
+
return NOT_REGISTERED;
|
|
255
|
+
const limit = args.limit ?? 3;
|
|
256
|
+
const res = await fetch(`${config.appUrl}/api/memory/reflections?projectId=${pid}&limit=${limit}`, {
|
|
257
|
+
headers: { authorization: `Bearer ${config.apiKey}` },
|
|
258
|
+
});
|
|
259
|
+
const data = await res.json();
|
|
260
|
+
if (!data.ok || !data.reflections) {
|
|
261
|
+
return { content: [{ type: "text", text: `인사이트가 아직 없어요. 태스크를 더 완료하면 AI가 분석을 생성해요.` }] };
|
|
262
|
+
}
|
|
263
|
+
const lines = [];
|
|
264
|
+
for (const r of data.reflections) {
|
|
265
|
+
const date = new Date(r.createdAt).toLocaleDateString("ko-KR");
|
|
266
|
+
lines.push(`## ${date} 분석 (${r.analyzedTaskCount}개 태스크, ${r.triggerReason === "threshold" ? "임계값 도달" : "정기"})`);
|
|
267
|
+
if (r.contextSummary)
|
|
268
|
+
lines.push(`\n**프로젝트 맥락:** ${r.contextSummary}`);
|
|
269
|
+
if (r.insights.length > 0) {
|
|
270
|
+
lines.push(`\n**인사이트:**`);
|
|
271
|
+
for (const ins of r.insights) {
|
|
272
|
+
const label = ins.type === "pattern" ? "패턴" : ins.type === "risk" ? "위험" : "인사이트";
|
|
273
|
+
lines.push(`- [${label}] ${ins.text}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (r.suggestedTasks.length > 0) {
|
|
277
|
+
lines.push(`\n**추천 태스크:**`);
|
|
278
|
+
for (const t of r.suggestedTasks) {
|
|
279
|
+
lines.push(`- ${t.title} (${t.priority}) — ${t.reason}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
lines.push("");
|
|
283
|
+
}
|
|
284
|
+
return { content: [{ type: "text", text: lines.join("\n") || "분석 결과가 없어요." }] };
|
|
285
|
+
});
|
|
286
|
+
server.tool("create_folder", "태스크 폴더를 새로 만들어요. brief의 폴더 목록에 없는 폴더가 필요할 때 사용하세요.", {
|
|
287
|
+
...cwdParam,
|
|
288
|
+
name: z.string().describe("폴더 이름"),
|
|
289
|
+
}, async (args) => {
|
|
290
|
+
if (!config)
|
|
291
|
+
return NOT_LOGGED_IN;
|
|
292
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
293
|
+
if (!pid)
|
|
294
|
+
return NOT_REGISTERED;
|
|
295
|
+
return { content: [{ type: "text", text: await handleCreateFolder(args, pid, config) }] };
|
|
296
|
+
});
|
|
297
|
+
server.tool("upload_prompt", "CLAUDE.md, AGENTS.md, SKILL.md 파일을 Haema에 업로드해요. 프롬프트/스킬 파일을 최신 상태로 동기화할 때 사용해요.", {
|
|
298
|
+
cwd: z.string().describe("프로젝트 절대경로"),
|
|
299
|
+
}, async (args) => {
|
|
300
|
+
if (!config)
|
|
301
|
+
return NOT_LOGGED_IN;
|
|
302
|
+
return { content: [{ type: "text", text: await handleUploadPrompt(args, config) }] };
|
|
303
|
+
});
|
|
304
|
+
server.tool("apply_hooks", "서버에서 프로젝트 SOP 훅을 가져와 로컬 Claude Code 설정에 적용해요. 반복 패턴에서 자동 생성된 훅 스크립트를 ~/.haema/hooks/에 배포하고 ~/.claude/settings.json에 등록해요.", cwdParam, async (args) => {
|
|
305
|
+
if (!config)
|
|
306
|
+
return NOT_LOGGED_IN;
|
|
307
|
+
const pid = await resolveProject({ cwd: args.cwd, defaultProjectId: await getDefaultPid() }, config);
|
|
308
|
+
if (!pid)
|
|
309
|
+
return NOT_REGISTERED;
|
|
310
|
+
return { content: [{ type: "text", text: await handleApplyHooks(pid, config) }] };
|
|
311
|
+
});
|
|
312
|
+
server.tool("signin", "Haema 계정으로 로그인해요. 브라우저가 자동으로 열려요.", {
|
|
313
|
+
appUrl: z.string().optional().describe("Haema 서버 URL (기본값: https://haema.jocodingax.ai)"),
|
|
314
|
+
}, async (args) => ({
|
|
315
|
+
content: [{ type: "text", text: await handleSignin(args) }],
|
|
316
|
+
}));
|
|
317
|
+
server.tool("whoami", "현재 로그인된 계정 정보를 확인해요.", {}, async () => ({
|
|
318
|
+
content: [{ type: "text", text: await handleWhoami() }],
|
|
319
|
+
}));
|
|
320
|
+
server.tool("signout", "현재 계정에서 로그아웃해요.", {}, async () => ({
|
|
321
|
+
content: [{ type: "text", text: await handleSignout() }],
|
|
322
|
+
}));
|
|
323
|
+
return server;
|
|
324
|
+
}
|
|
325
|
+
export async function startStdio(config, cwd) {
|
|
326
|
+
const server = createServer(config, cwd);
|
|
327
|
+
const transport = new StdioServerTransport();
|
|
328
|
+
await server.connect(transport);
|
|
329
|
+
}
|
|
330
|
+
export async function startHttp(port, config, cwd) {
|
|
331
|
+
const mcpServer = createServer(config, cwd);
|
|
332
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
333
|
+
await mcpServer.connect(transport);
|
|
334
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
335
|
+
await transport.handleRequest(req, res);
|
|
336
|
+
});
|
|
337
|
+
httpServer.listen(port, "127.0.0.1", () => {
|
|
338
|
+
console.error(`haema-memory MCP HTTP 서버 실행 중: http://127.0.0.1:${port}/mcp`);
|
|
339
|
+
});
|
|
340
|
+
await new Promise((_, reject) => {
|
|
341
|
+
httpServer.on("error", reject);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { mcpPost } from "../mcpClient.js";
|
|
2
|
+
export async function handleAddTask(args, projectId, config) {
|
|
3
|
+
const data = await mcpPost(config, "/api/memory/tasks", {
|
|
4
|
+
projectId,
|
|
5
|
+
title: args.title,
|
|
6
|
+
description: args.description,
|
|
7
|
+
module: args.module,
|
|
8
|
+
priority: args.priority,
|
|
9
|
+
folderId: args.folderId,
|
|
10
|
+
});
|
|
11
|
+
if (!data.ok)
|
|
12
|
+
throw new Error(data.error);
|
|
13
|
+
return `태스크 생성됨: #${data.task.seq} "${data.task.title}"`;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=addTask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addTask.js","sourceRoot":"","sources":["../../../src/mcp/tools/addTask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAoG,EACpG,SAAiB,EACjB,MAAiB;IAEjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAe,MAAM,EAAE,mBAAmB,EAAE;QACpE,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,aAAa,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { mcpGet } from "../mcpClient.js";
|
|
5
|
+
const AUTO_LOG_SESSION_SCRIPT = `#!/bin/bash
|
|
6
|
+
# haema auto-log-session — Claude Code Stop 훅 (자동 설치됨)
|
|
7
|
+
AUTH_FILE="$HOME/.haema/auth.json"
|
|
8
|
+
[ -f "$AUTH_FILE" ] || exit 0
|
|
9
|
+
|
|
10
|
+
HAEMA_HOOK_INPUT=$(cat 2>/dev/null || echo "{}") HAEMA_CWD="$PWD" node --input-type=module << 'JSEOF' 2>/dev/null || true
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
let auth;
|
|
13
|
+
try { auth = JSON.parse(readFileSync(process.env.HOME + '/.haema/auth.json', 'utf8')); }
|
|
14
|
+
catch { process.exit(0); }
|
|
15
|
+
if (!auth.apiKey || !auth.appUrl) process.exit(0);
|
|
16
|
+
let sessionId;
|
|
17
|
+
try { sessionId = JSON.parse(process.env.HAEMA_HOOK_INPUT || '{}').session_id; } catch {}
|
|
18
|
+
const body = JSON.stringify({ cwd: process.env.HAEMA_CWD, sessionId: sessionId || undefined });
|
|
19
|
+
try {
|
|
20
|
+
await fetch(auth.appUrl + '/api/memory/sessions/auto', {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: { 'Authorization': 'Bearer ' + auth.apiKey, 'Content-Type': 'application/json' },
|
|
23
|
+
body,
|
|
24
|
+
signal: AbortSignal.timeout(15000),
|
|
25
|
+
});
|
|
26
|
+
} catch {}
|
|
27
|
+
JSEOF
|
|
28
|
+
`;
|
|
29
|
+
export async function handleApplyHooks(projectId, config) {
|
|
30
|
+
const data = await mcpGet(config, "/api/memory/hooks", { projectId });
|
|
31
|
+
if (!data.ok)
|
|
32
|
+
throw new Error(data.error);
|
|
33
|
+
const { hooks } = data;
|
|
34
|
+
const hooksDir = path.join(homedir(), ".haema", "hooks");
|
|
35
|
+
await fs.mkdir(hooksDir, { recursive: true });
|
|
36
|
+
// Deploy auto-log-session Stop hook
|
|
37
|
+
const stopScriptPath = path.join(hooksDir, "auto-log-session.sh");
|
|
38
|
+
await fs.writeFile(stopScriptPath, AUTO_LOG_SESSION_SCRIPT, { encoding: "utf8", mode: 0o755 });
|
|
39
|
+
// Write each hook script file
|
|
40
|
+
for (const hook of hooks) {
|
|
41
|
+
const scriptPath = path.join(hooksDir, `${hook.slug}.sh`);
|
|
42
|
+
await fs.writeFile(scriptPath, hook.hookScript, { encoding: "utf8", mode: 0o755 });
|
|
43
|
+
}
|
|
44
|
+
// Update ~/.claude/settings.json
|
|
45
|
+
const settingsPath = path.join(homedir(), ".claude", "settings.json");
|
|
46
|
+
await fs.mkdir(path.dirname(settingsPath), { recursive: true });
|
|
47
|
+
let settings = {};
|
|
48
|
+
try {
|
|
49
|
+
const raw = await fs.readFile(settingsPath, "utf8");
|
|
50
|
+
settings = JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// create fresh settings
|
|
54
|
+
}
|
|
55
|
+
const allHooks = (settings.hooks ?? {});
|
|
56
|
+
// Remove stale haema SOP hooks (identified by .haema/hooks/ in command path)
|
|
57
|
+
const haemaHooksPath = path.join(homedir(), ".haema", "hooks");
|
|
58
|
+
let removed = 0;
|
|
59
|
+
for (const event of Object.keys(allHooks)) {
|
|
60
|
+
const before = allHooks[event].length;
|
|
61
|
+
allHooks[event] = allHooks[event].filter((group) => !group.hooks.some((h) => h.command.includes(haemaHooksPath) && !h.command.includes("suggest-skill.sh") && !h.command.includes("auto-log-session")));
|
|
62
|
+
removed += before - allHooks[event].length;
|
|
63
|
+
}
|
|
64
|
+
// Register Stop hook for auto-log-session
|
|
65
|
+
const stopGroups = allHooks["Stop"] ?? [];
|
|
66
|
+
const stopCommand = `bash ${stopScriptPath}`;
|
|
67
|
+
if (!stopGroups.some((g) => g.hooks.some((h) => h.command === stopCommand))) {
|
|
68
|
+
stopGroups.push({ hooks: [{ type: "command", command: stopCommand, statusMessage: "Haema: 세션 자동 저장" }] });
|
|
69
|
+
}
|
|
70
|
+
allHooks["Stop"] = stopGroups;
|
|
71
|
+
// Add new SOP hooks grouped by event
|
|
72
|
+
const byEvent = new Map();
|
|
73
|
+
for (const hook of hooks) {
|
|
74
|
+
const arr = byEvent.get(hook.hookEvent) ?? [];
|
|
75
|
+
arr.push(hook);
|
|
76
|
+
byEvent.set(hook.hookEvent, arr);
|
|
77
|
+
}
|
|
78
|
+
for (const [event, eventHooks] of byEvent) {
|
|
79
|
+
const existingGroups = allHooks[event] ?? [];
|
|
80
|
+
for (const hook of eventHooks) {
|
|
81
|
+
const scriptPath = path.join(hooksDir, `${hook.slug}.sh`);
|
|
82
|
+
const command = `bash ${scriptPath}`;
|
|
83
|
+
const alreadyExists = existingGroups.some((g) => g.hooks.some((h) => h.command === command));
|
|
84
|
+
if (!alreadyExists) {
|
|
85
|
+
existingGroups.push({
|
|
86
|
+
matcher: hook.hookMatcher,
|
|
87
|
+
hooks: [{ type: "command", command, statusMessage: `SOP: ${hook.name}` }],
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
allHooks[event] = existingGroups;
|
|
92
|
+
}
|
|
93
|
+
settings.hooks = allHooks;
|
|
94
|
+
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
95
|
+
const lines = [];
|
|
96
|
+
lines.push(`✅ Stop 훅 등록 완료 — 세션 종료 시 작업 내역이 자동으로 저장돼요.`);
|
|
97
|
+
if (hooks.length === 0) {
|
|
98
|
+
lines.push("등록할 SOP 훅이 없어요. 태스크가 쌓이면 AI가 자동으로 패턴을 감지해 훅을 생성해요.");
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
lines.push(`✅ ${hooks.length}개 SOP 훅 적용 완료 (${removed > 0 ? `${removed}개 교체` : "신규 등록"})`);
|
|
102
|
+
for (const hook of hooks) {
|
|
103
|
+
lines.push(`- [${hook.hookEvent}:${hook.hookMatcher}] ${hook.name}`);
|
|
104
|
+
}
|
|
105
|
+
lines.push(`\n스크립트 위치: ${hooksDir}/`);
|
|
106
|
+
lines.push(`다음 세션부터 "${hooks.map((h) => h.hookMatcher).join(", ")}" 툴 호출 시 자동으로 SOP 리마인더가 실행돼요.`);
|
|
107
|
+
}
|
|
108
|
+
return lines.join("\n");
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=applyHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyHooks.js","sourceRoot":"","sources":["../../../src/mcp/tools/applyHooks.ts"],"names":[],"mappings":"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"}
|