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.
Files changed (2) hide show
  1. package/index.js +94 -35
  2. 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: '할일을 z_DocuKing/z_Todo/z_Todo.md 파일에 추가하거나 완료 표시합니다. 단일 파일에 계속 누적되어 전체 작업 히스토리가 됩니다. 논의 후 할일이 생기면 바로 등록하세요.',
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
- // z_Todo 폴더 경로
2130
- const todoBasePath = path.join(localPath, 'z_DocuKing', 'z_Todo');
2131
- const todoFilePath = path.join(todoBasePath, 'z_Todo.md');
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 dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
2165
- const timeStr = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
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
- const newTodo = `${newId}. - [ ] ${todo} (${dateStr})\n`;
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: `✓ TODO 추가 완료!
2234
+ text: `✓ 킹투두에 등록했습니다!
2184
2235
 
2185
- 📝 #${newId}: ${todo}
2186
- 📅 등록: ${dateStr} ${timeStr}
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}\\. - \\[)( )(\\].*)$`, 'm');
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: `오류: TODO #${todoId}를 찾을 수 없습니다.` }],
2264
+ content: [{ type: 'text', text: `오류: 킹투두 #${todoId}를 찾을 수 없습니다.` }],
2207
2265
  };
2208
2266
  }
2209
2267
 
2210
- // [ ] -> [x] 변경 + 완료 날짜 추가
2268
+ // ⚙️ -> 변경 + 완료 날짜 추가 (등록일/완료일)
2211
2269
  const updatedContent = content.replace(
2212
2270
  todoLinePattern,
2213
- `$1x$3 ✓${dateStr}`
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 todoContent = matched[0].replace(/^\d+\. - \[ \] /, '').replace(/ \(\d{4}-\d{2}-\d{2}\)$/, '');
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: `✓ TODO #${todoId} 완료!
2283
+ text: `✓ 킹투두 #${todoId} 완료!
2225
2284
 
2226
- ✅ ${todoContent}
2227
- 📅 완료: ${dateStr} ${timeStr}`,
2285
+ ✅ ${todoKeyword}
2286
+ 📅 완료: ${dateStr}`,
2228
2287
  }],
2229
2288
  };
2230
2289
  }
2231
2290
 
2232
2291
  if (action === 'list') {
2233
- // 미완료 TODO 추출
2234
- const pendingPattern = /^(\d+)\. - \[ \] (.+)$/gm;
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], content: listMatch[2] });
2297
+ pendingTodos.push({ id: listMatch[1], keyword: listMatch[2], date: listMatch[3] });
2239
2298
  }
2240
2299
 
2241
- // 완료된 TODO 수 세기
2242
- const completedCount = (content.match(/- \[x\]/g) || []).length;
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: `📋 미완료 TODO: 없음
2307
+ text: `📋 킹투두 미결: 없음
2249
2308
 
2250
- 완료된 TODO: ${completedCount}개
2251
- 📁 전체 기록: z_DocuKing/z_Todo/z_Todo.md`,
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.content}`).join('\n');
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: `📋 미완료 TODO: ${pendingTodos.length}개
2320
+ text: `📋 킹투두 미결: ${pendingTodos.length}개
2262
2321
 
2263
2322
  ${listText}
2264
2323
 
2265
- 완료된 TODO: ${completedCount}개
2266
- 📁 전체 기록: z_DocuKing/z_Todo/z_Todo.md`,
2324
+ 완료: ${completedCount}개
2325
+ 📁 전체 기록: z_DocuKing/z_King_Todo/z_King_Todo.md`,
2267
2326
  }],
2268
2327
  };
2269
2328
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docuking-mcp",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "DocuKing MCP Server - AI 시대의 문서 협업 플랫폼",
5
5
  "type": "module",
6
6
  "main": "index.js",