docuking-mcp 1.8.0 → 1.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/index.js +94 -35
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -508,7 +508,26 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
508
508
|
},
|
|
509
509
|
{
|
|
510
510
|
name: 'docuking_todo',
|
|
511
|
-
description:
|
|
511
|
+
description: `킹투두(King Todo) - 프로젝트 공식 할일을 z_DocuKing/z_King_Todo/z_King_Todo.md에 관리합니다.
|
|
512
|
+
|
|
513
|
+
**AI 내장 TodoWrite와 다름!** 킹투두는 웹에 동기화되고 팀과 공유됩니다.
|
|
514
|
+
|
|
515
|
+
**작성 형식:**
|
|
516
|
+
\`\`\`
|
|
517
|
+
1. ✅ **[태그] 키워드** 12.30/12.30
|
|
518
|
+
설명 (7칸 들여쓰기)
|
|
519
|
+
|
|
520
|
+
2. ⚙️ **[태그] 키워드** 12.30
|
|
521
|
+
설명
|
|
522
|
+
\`\`\`
|
|
523
|
+
|
|
524
|
+
**형식 규칙:**
|
|
525
|
+
- ✅ 완료 / ⚙️ 진행중
|
|
526
|
+
- **[태그] 키워드** 볼드 처리
|
|
527
|
+
- 날짜 1개 = 등록일(진행중), 2개 = 등록일/완료일(완료)
|
|
528
|
+
- 설명은 7칸 들여쓰기 ([ 기호 아래 정렬)
|
|
529
|
+
|
|
530
|
+
**사용자에게 "킹투두에 등록했습니다" 형식으로 보고하세요.**`,
|
|
512
531
|
inputSchema: {
|
|
513
532
|
type: 'object',
|
|
514
533
|
properties: {
|
|
@@ -523,7 +542,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
523
542
|
},
|
|
524
543
|
todo: {
|
|
525
544
|
type: 'string',
|
|
526
|
-
description: '할일 내용 (add 시 필수)',
|
|
545
|
+
description: '할일 내용 (add 시 필수). 형식: "[태그] 키워드 - 설명" 예: "[보안] API 인증 강화 - JWT 토큰 검증"',
|
|
527
546
|
},
|
|
528
547
|
todoId: {
|
|
529
548
|
type: 'number',
|
|
@@ -2122,13 +2141,13 @@ function generatePlanId() {
|
|
|
2122
2141
|
return id;
|
|
2123
2142
|
}
|
|
2124
2143
|
|
|
2125
|
-
// docuking_todo 구현 -
|
|
2144
|
+
// docuking_todo 구현 - 킹투두 (단일 파일 누적)
|
|
2126
2145
|
async function handleTodo(args) {
|
|
2127
2146
|
const { localPath, action, todo, todoId } = args;
|
|
2128
2147
|
|
|
2129
|
-
//
|
|
2130
|
-
const todoBasePath = path.join(localPath, 'z_DocuKing', '
|
|
2131
|
-
const todoFilePath = path.join(todoBasePath, '
|
|
2148
|
+
// z_King_Todo 폴더 경로
|
|
2149
|
+
const todoBasePath = path.join(localPath, 'z_DocuKing', 'z_King_Todo');
|
|
2150
|
+
const todoFilePath = path.join(todoBasePath, 'z_King_Todo.md');
|
|
2132
2151
|
|
|
2133
2152
|
// 폴더 생성
|
|
2134
2153
|
if (!fs.existsSync(todoBasePath)) {
|
|
@@ -2139,8 +2158,7 @@ async function handleTodo(args) {
|
|
|
2139
2158
|
if (!fs.existsSync(todoFilePath)) {
|
|
2140
2159
|
const header = `# TODO 목록
|
|
2141
2160
|
|
|
2142
|
-
>
|
|
2143
|
-
> - [ ] 미완료 / - [x] 완료 (완료 시 날짜 추가)
|
|
2161
|
+
> 날짜 1개 = 등록일 (진행중) / 날짜 2개 = 등록일/완료일 (완료)
|
|
2144
2162
|
|
|
2145
2163
|
---
|
|
2146
2164
|
|
|
@@ -2161,8 +2179,9 @@ async function handleTodo(args) {
|
|
|
2161
2179
|
}
|
|
2162
2180
|
|
|
2163
2181
|
const now = new Date();
|
|
2164
|
-
const
|
|
2165
|
-
const
|
|
2182
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
2183
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
2184
|
+
const dateStr = `${month}.${day}`;
|
|
2166
2185
|
|
|
2167
2186
|
if (action === 'add') {
|
|
2168
2187
|
if (!todo) {
|
|
@@ -2172,7 +2191,39 @@ async function handleTodo(args) {
|
|
|
2172
2191
|
}
|
|
2173
2192
|
|
|
2174
2193
|
const newId = maxId + 1;
|
|
2175
|
-
|
|
2194
|
+
|
|
2195
|
+
// todo에서 태그와 키워드, 설명 분리
|
|
2196
|
+
// 형식: "[태그] 키워드 - 설명" 또는 "[태그] 키워드"
|
|
2197
|
+
let tag = '';
|
|
2198
|
+
let keyword = '';
|
|
2199
|
+
let description = '';
|
|
2200
|
+
|
|
2201
|
+
const tagMatch = todo.match(/^\[([^\]]+)\]\s*/);
|
|
2202
|
+
if (tagMatch) {
|
|
2203
|
+
tag = tagMatch[1];
|
|
2204
|
+
const rest = todo.slice(tagMatch[0].length);
|
|
2205
|
+
const descSplit = rest.split(/\s*[-–]\s*/);
|
|
2206
|
+
keyword = descSplit[0].trim();
|
|
2207
|
+
description = descSplit.slice(1).join(' - ').trim();
|
|
2208
|
+
} else {
|
|
2209
|
+
// 태그 없이 입력된 경우
|
|
2210
|
+
const descSplit = todo.split(/\s*[-–]\s*/);
|
|
2211
|
+
keyword = descSplit[0].trim();
|
|
2212
|
+
description = descSplit.slice(1).join(' - ').trim();
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
// 킹투두 형식으로 작성
|
|
2216
|
+
let newTodo;
|
|
2217
|
+
if (tag) {
|
|
2218
|
+
newTodo = `${newId}. ⚙️ **[${tag}] ${keyword}** ${dateStr}\n`;
|
|
2219
|
+
} else {
|
|
2220
|
+
newTodo = `${newId}. ⚙️ **${keyword}** ${dateStr}\n`;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
if (description) {
|
|
2224
|
+
newTodo += ` ${description}\n`;
|
|
2225
|
+
}
|
|
2226
|
+
newTodo += '\n';
|
|
2176
2227
|
|
|
2177
2228
|
// 파일 끝에 추가
|
|
2178
2229
|
fs.appendFileSync(todoFilePath, newTodo, 'utf-8');
|
|
@@ -2180,10 +2231,10 @@ async function handleTodo(args) {
|
|
|
2180
2231
|
return {
|
|
2181
2232
|
content: [{
|
|
2182
2233
|
type: 'text',
|
|
2183
|
-
text: `✓
|
|
2234
|
+
text: `✓ 킹투두에 등록했습니다!
|
|
2184
2235
|
|
|
2185
|
-
📝 #${newId}: ${
|
|
2186
|
-
📅 등록: ${dateStr}
|
|
2236
|
+
📝 #${newId}: ${tag ? `[${tag}] ` : ''}${keyword}${description ? ` - ${description}` : ''}
|
|
2237
|
+
📅 등록: ${dateStr}
|
|
2187
2238
|
|
|
2188
2239
|
💡 완료 시: docuking_todo(action: "done", todoId: ${newId})`,
|
|
2189
2240
|
}],
|
|
@@ -2197,73 +2248,81 @@ async function handleTodo(args) {
|
|
|
2197
2248
|
};
|
|
2198
2249
|
}
|
|
2199
2250
|
|
|
2200
|
-
// 해당 번호의 TODO 찾아서
|
|
2201
|
-
const todoLinePattern = new RegExp(`^(${todoId}\\.
|
|
2251
|
+
// 해당 번호의 TODO 찾아서 ⚙️ -> ✅ 변경 및 날짜 추가
|
|
2252
|
+
const todoLinePattern = new RegExp(`^(${todoId}\\. )⚙️( \\*\\*.*\\*\\* )(\\d+\\.\\d+)(.*)$`, 'm');
|
|
2202
2253
|
const matched = content.match(todoLinePattern);
|
|
2203
2254
|
|
|
2204
2255
|
if (!matched) {
|
|
2256
|
+
// 이미 완료된 항목인지 확인
|
|
2257
|
+
const completedPattern = new RegExp(`^${todoId}\\. ✅`, 'm');
|
|
2258
|
+
if (completedPattern.test(content)) {
|
|
2259
|
+
return {
|
|
2260
|
+
content: [{ type: 'text', text: `킹투두 #${todoId}는 이미 완료 상태입니다.` }],
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2205
2263
|
return {
|
|
2206
|
-
content: [{ type: 'text', text: `오류:
|
|
2264
|
+
content: [{ type: 'text', text: `오류: 킹투두 #${todoId}를 찾을 수 없습니다.` }],
|
|
2207
2265
|
};
|
|
2208
2266
|
}
|
|
2209
2267
|
|
|
2210
|
-
//
|
|
2268
|
+
// ⚙️ -> ✅ 변경 + 완료 날짜 추가 (등록일/완료일)
|
|
2211
2269
|
const updatedContent = content.replace(
|
|
2212
2270
|
todoLinePattern,
|
|
2213
|
-
`$
|
|
2271
|
+
`$1✅$2$3/${dateStr}$4`
|
|
2214
2272
|
);
|
|
2215
2273
|
|
|
2216
2274
|
fs.writeFileSync(todoFilePath, updatedContent, 'utf-8');
|
|
2217
2275
|
|
|
2218
2276
|
// 완료된 TODO 내용 추출
|
|
2219
|
-
const
|
|
2277
|
+
const keywordMatch = matched[2].match(/\*\*(.+)\*\*/);
|
|
2278
|
+
const todoKeyword = keywordMatch ? keywordMatch[1] : '';
|
|
2220
2279
|
|
|
2221
2280
|
return {
|
|
2222
2281
|
content: [{
|
|
2223
2282
|
type: 'text',
|
|
2224
|
-
text: `✓
|
|
2283
|
+
text: `✓ 킹투두 #${todoId} 완료!
|
|
2225
2284
|
|
|
2226
|
-
✅ ${
|
|
2227
|
-
📅 완료: ${dateStr}
|
|
2285
|
+
✅ ${todoKeyword}
|
|
2286
|
+
📅 완료: ${dateStr}`,
|
|
2228
2287
|
}],
|
|
2229
2288
|
};
|
|
2230
2289
|
}
|
|
2231
2290
|
|
|
2232
2291
|
if (action === 'list') {
|
|
2233
|
-
// 미완료 TODO
|
|
2234
|
-
const pendingPattern = /^(\d+)\.
|
|
2292
|
+
// 미완료(⚙️) TODO 추출
|
|
2293
|
+
const pendingPattern = /^(\d+)\. ⚙️ \*\*(.+)\*\* (\d+\.\d+)/gm;
|
|
2235
2294
|
const pendingTodos = [];
|
|
2236
2295
|
let listMatch;
|
|
2237
2296
|
while ((listMatch = pendingPattern.exec(content)) !== null) {
|
|
2238
|
-
pendingTodos.push({ id: listMatch[1],
|
|
2297
|
+
pendingTodos.push({ id: listMatch[1], keyword: listMatch[2], date: listMatch[3] });
|
|
2239
2298
|
}
|
|
2240
2299
|
|
|
2241
|
-
// 완료된 TODO 수 세기
|
|
2242
|
-
const completedCount = (content.match(
|
|
2300
|
+
// 완료된(✅) TODO 수 세기
|
|
2301
|
+
const completedCount = (content.match(/^(\d+)\. ✅/gm) || []).length;
|
|
2243
2302
|
|
|
2244
2303
|
if (pendingTodos.length === 0) {
|
|
2245
2304
|
return {
|
|
2246
2305
|
content: [{
|
|
2247
2306
|
type: 'text',
|
|
2248
|
-
text: `📋
|
|
2307
|
+
text: `📋 킹투두 미결: 없음
|
|
2249
2308
|
|
|
2250
|
-
✅
|
|
2251
|
-
📁 전체 기록: z_DocuKing/
|
|
2309
|
+
✅ 완료: ${completedCount}개
|
|
2310
|
+
📁 전체 기록: z_DocuKing/z_King_Todo/z_King_Todo.md`,
|
|
2252
2311
|
}],
|
|
2253
2312
|
};
|
|
2254
2313
|
}
|
|
2255
2314
|
|
|
2256
|
-
const listText = pendingTodos.map(t => ` #${t.id}: ${t.
|
|
2315
|
+
const listText = pendingTodos.map(t => ` #${t.id}: ${t.keyword} (${t.date})`).join('\n');
|
|
2257
2316
|
|
|
2258
2317
|
return {
|
|
2259
2318
|
content: [{
|
|
2260
2319
|
type: 'text',
|
|
2261
|
-
text: `📋
|
|
2320
|
+
text: `📋 킹투두 미결: ${pendingTodos.length}개
|
|
2262
2321
|
|
|
2263
2322
|
${listText}
|
|
2264
2323
|
|
|
2265
|
-
✅
|
|
2266
|
-
📁 전체 기록: z_DocuKing/
|
|
2324
|
+
✅ 완료: ${completedCount}개
|
|
2325
|
+
📁 전체 기록: z_DocuKing/z_King_Todo/z_King_Todo.md`,
|
|
2267
2326
|
}],
|
|
2268
2327
|
};
|
|
2269
2328
|
}
|