algokit-mcp 1.0.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/README.md +137 -0
- package/dist/api/boj-scraper.d.ts +68 -0
- package/dist/api/boj-scraper.d.ts.map +1 -0
- package/dist/api/boj-scraper.js +197 -0
- package/dist/api/boj-scraper.js.map +1 -0
- package/dist/api/programmers-scraper.d.ts +70 -0
- package/dist/api/programmers-scraper.d.ts.map +1 -0
- package/dist/api/programmers-scraper.js +303 -0
- package/dist/api/programmers-scraper.js.map +1 -0
- package/dist/api/solvedac-client.d.ts +67 -0
- package/dist/api/solvedac-client.d.ts.map +1 -0
- package/dist/api/solvedac-client.js +220 -0
- package/dist/api/solvedac-client.js.map +1 -0
- package/dist/api/types.d.ts +125 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +110 -0
- package/dist/api/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +594 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/hint-guide.d.ts +73 -0
- package/dist/prompts/hint-guide.d.ts.map +1 -0
- package/dist/prompts/hint-guide.js +174 -0
- package/dist/prompts/hint-guide.js.map +1 -0
- package/dist/prompts/programmers-hint-guide.d.ts +38 -0
- package/dist/prompts/programmers-hint-guide.d.ts.map +1 -0
- package/dist/prompts/programmers-hint-guide.js +134 -0
- package/dist/prompts/programmers-hint-guide.js.map +1 -0
- package/dist/services/code-analyzer.d.ts +46 -0
- package/dist/services/code-analyzer.d.ts.map +1 -0
- package/dist/services/code-analyzer.js +177 -0
- package/dist/services/code-analyzer.js.map +1 -0
- package/dist/services/hint-generator.d.ts +60 -0
- package/dist/services/hint-generator.d.ts.map +1 -0
- package/dist/services/hint-generator.js +222 -0
- package/dist/services/hint-generator.js.map +1 -0
- package/dist/services/problem-analyzer.d.ts +38 -0
- package/dist/services/problem-analyzer.d.ts.map +1 -0
- package/dist/services/problem-analyzer.js +114 -0
- package/dist/services/problem-analyzer.js.map +1 -0
- package/dist/services/programmers-problem-analyzer.d.ts +26 -0
- package/dist/services/programmers-problem-analyzer.d.ts.map +1 -0
- package/dist/services/programmers-problem-analyzer.js +64 -0
- package/dist/services/programmers-problem-analyzer.js.map +1 -0
- package/dist/services/programmers-review-template-generator.d.ts +27 -0
- package/dist/services/programmers-review-template-generator.d.ts.map +1 -0
- package/dist/services/programmers-review-template-generator.js +153 -0
- package/dist/services/programmers-review-template-generator.js.map +1 -0
- package/dist/services/review-generator.d.ts +51 -0
- package/dist/services/review-generator.d.ts.map +1 -0
- package/dist/services/review-generator.js +149 -0
- package/dist/services/review-generator.js.map +1 -0
- package/dist/services/review-template-generator.d.ts +27 -0
- package/dist/services/review-template-generator.d.ts.map +1 -0
- package/dist/services/review-template-generator.js +163 -0
- package/dist/services/review-template-generator.js.map +1 -0
- package/dist/templates/review-guideline.md +89 -0
- package/dist/tools/analyze-code-submission-boj.d.ts +67 -0
- package/dist/tools/analyze-code-submission-boj.d.ts.map +1 -0
- package/dist/tools/analyze-code-submission-boj.js +89 -0
- package/dist/tools/analyze-code-submission-boj.js.map +1 -0
- package/dist/tools/analyze-code-submission-programmers.d.ts +60 -0
- package/dist/tools/analyze-code-submission-programmers.d.ts.map +1 -0
- package/dist/tools/analyze-code-submission-programmers.js +83 -0
- package/dist/tools/analyze-code-submission-programmers.js.map +1 -0
- package/dist/tools/analyze-code-submission.d.ts +67 -0
- package/dist/tools/analyze-code-submission.d.ts.map +1 -0
- package/dist/tools/analyze-code-submission.js +89 -0
- package/dist/tools/analyze-code-submission.js.map +1 -0
- package/dist/tools/analyze-problem-boj.d.ts +48 -0
- package/dist/tools/analyze-problem-boj.d.ts.map +1 -0
- package/dist/tools/analyze-problem-boj.js +52 -0
- package/dist/tools/analyze-problem-boj.js.map +1 -0
- package/dist/tools/analyze-problem-programmers.d.ts +48 -0
- package/dist/tools/analyze-problem-programmers.d.ts.map +1 -0
- package/dist/tools/analyze-problem-programmers.js +53 -0
- package/dist/tools/analyze-problem-programmers.js.map +1 -0
- package/dist/tools/analyze-problem.d.ts +48 -0
- package/dist/tools/analyze-problem.d.ts.map +1 -0
- package/dist/tools/analyze-problem.js +52 -0
- package/dist/tools/analyze-problem.js.map +1 -0
- package/dist/tools/create-review.d.ts +47 -0
- package/dist/tools/create-review.d.ts.map +1 -0
- package/dist/tools/create-review.js +122 -0
- package/dist/tools/create-review.js.map +1 -0
- package/dist/tools/fetch-problem-content-boj.d.ts +49 -0
- package/dist/tools/fetch-problem-content-boj.d.ts.map +1 -0
- package/dist/tools/fetch-problem-content-boj.js +93 -0
- package/dist/tools/fetch-problem-content-boj.js.map +1 -0
- package/dist/tools/fetch-problem-content-programmers.d.ts +46 -0
- package/dist/tools/fetch-problem-content-programmers.d.ts.map +1 -0
- package/dist/tools/fetch-problem-content-programmers.js +74 -0
- package/dist/tools/fetch-problem-content-programmers.js.map +1 -0
- package/dist/tools/fetch-problem-content.d.ts +49 -0
- package/dist/tools/fetch-problem-content.d.ts.map +1 -0
- package/dist/tools/fetch-problem-content.js +93 -0
- package/dist/tools/fetch-problem-content.js.map +1 -0
- package/dist/tools/generate-hint-boj.d.ts +42 -0
- package/dist/tools/generate-hint-boj.d.ts.map +1 -0
- package/dist/tools/generate-hint-boj.js +80 -0
- package/dist/tools/generate-hint-boj.js.map +1 -0
- package/dist/tools/generate-hint-programmers.d.ts +42 -0
- package/dist/tools/generate-hint-programmers.d.ts.map +1 -0
- package/dist/tools/generate-hint-programmers.js +78 -0
- package/dist/tools/generate-hint-programmers.js.map +1 -0
- package/dist/tools/generate-hint.d.ts +42 -0
- package/dist/tools/generate-hint.d.ts.map +1 -0
- package/dist/tools/generate-hint.js +80 -0
- package/dist/tools/generate-hint.js.map +1 -0
- package/dist/tools/generate-review-template-boj.d.ts +48 -0
- package/dist/tools/generate-review-template-boj.d.ts.map +1 -0
- package/dist/tools/generate-review-template-boj.js +52 -0
- package/dist/tools/generate-review-template-boj.js.map +1 -0
- package/dist/tools/generate-review-template-programmers.d.ts +48 -0
- package/dist/tools/generate-review-template-programmers.d.ts.map +1 -0
- package/dist/tools/generate-review-template-programmers.js +53 -0
- package/dist/tools/generate-review-template-programmers.js.map +1 -0
- package/dist/tools/generate-review-template.d.ts +48 -0
- package/dist/tools/generate-review-template.d.ts.map +1 -0
- package/dist/tools/generate-review-template.js +52 -0
- package/dist/tools/generate-review-template.js.map +1 -0
- package/dist/tools/get-hint.d.ts +41 -0
- package/dist/tools/get-hint.d.ts.map +1 -0
- package/dist/tools/get-hint.js +108 -0
- package/dist/tools/get-hint.js.map +1 -0
- package/dist/tools/get-problem.d.ts +22 -0
- package/dist/tools/get-problem.d.ts.map +1 -0
- package/dist/tools/get-problem.js +89 -0
- package/dist/tools/get-problem.js.map +1 -0
- package/dist/tools/get-programmers-problem.d.ts +53 -0
- package/dist/tools/get-programmers-problem.d.ts.map +1 -0
- package/dist/tools/get-programmers-problem.js +161 -0
- package/dist/tools/get-programmers-problem.js.map +1 -0
- package/dist/tools/search-problems.d.ts +42 -0
- package/dist/tools/search-problems.d.ts.map +1 -0
- package/dist/tools/search-problems.js +123 -0
- package/dist/tools/search-problems.js.map +1 -0
- package/dist/tools/search-programmers-problems.d.ts +73 -0
- package/dist/tools/search-programmers-problems.d.ts.map +1 -0
- package/dist/tools/search-programmers-problems.js +171 -0
- package/dist/tools/search-programmers-problems.js.map +1 -0
- package/dist/tools/search-tags.d.ts +22 -0
- package/dist/tools/search-tags.d.ts.map +1 -0
- package/dist/tools/search-tags.js +70 -0
- package/dist/tools/search-tags.js.map +1 -0
- package/dist/types/analysis.d.ts +211 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +11 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/problem-content.d.ts +110 -0
- package/dist/types/problem-content.d.ts.map +1 -0
- package/dist/types/problem-content.js +7 -0
- package/dist/types/problem-content.js.map +1 -0
- package/dist/types/programmers.d.ts +72 -0
- package/dist/types/programmers.d.ts.map +1 -0
- package/dist/types/programmers.js +5 -0
- package/dist/types/programmers.js.map +1 -0
- package/dist/utils/browser-pool.d.ts +93 -0
- package/dist/utils/browser-pool.d.ts.map +1 -0
- package/dist/utils/browser-pool.js +193 -0
- package/dist/utils/browser-pool.js.map +1 -0
- package/dist/utils/cache-stats.d.ts +60 -0
- package/dist/utils/cache-stats.d.ts.map +1 -0
- package/dist/utils/cache-stats.js +78 -0
- package/dist/utils/cache-stats.js.map +1 -0
- package/dist/utils/cache.d.ts +72 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +99 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/html-parser.d.ts +57 -0
- package/dist/utils/html-parser.d.ts.map +1 -0
- package/dist/utils/html-parser.js +383 -0
- package/dist/utils/html-parser.js.map +1 -0
- package/dist/utils/lru-cache.d.ts +124 -0
- package/dist/utils/lru-cache.d.ts.map +1 -0
- package/dist/utils/lru-cache.js +259 -0
- package/dist/utils/lru-cache.js.map +1 -0
- package/dist/utils/programmers-converter.d.ts +15 -0
- package/dist/utils/programmers-converter.d.ts.map +1 -0
- package/dist/utils/programmers-converter.js +41 -0
- package/dist/utils/programmers-converter.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +145 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +244 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/tier-converter.d.ts +108 -0
- package/dist/utils/tier-converter.d.ts.map +1 -0
- package/dist/utils/tier-converter.js +198 -0
- package/dist/utils/tier-converter.js.map +1 -0
- package/dist/utils/url-parser.d.ts +25 -0
- package/dist/utils/url-parser.d.ts.map +1 -0
- package/dist/utils/url-parser.js +45 -0
- package/dist/utils/url-parser.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch_problem_content_boj MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* Phase 6 - P6-004: BOJ 문제 본문 스크래핑 MCP 도구 구현
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { BOJScraper, BojFetchError } from '../api/boj-scraper.js';
|
|
8
|
+
import { parseProblemContent, HtmlParseError } from '../utils/html-parser.js';
|
|
9
|
+
/**
|
|
10
|
+
* 입력 스키마
|
|
11
|
+
*/
|
|
12
|
+
export const FetchProblemContentBOJInputSchema = z.object({
|
|
13
|
+
problem_id: z.number().int().positive()
|
|
14
|
+
.describe('백준 문제 번호'),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* fetch_problem_content_boj 도구 핸들러
|
|
18
|
+
*
|
|
19
|
+
* @param args - 입력 인자 (problem_id)
|
|
20
|
+
* @returns ProblemContent JSON 문자열
|
|
21
|
+
* @throws {Error} 검증 실패, 스크래핑 실패, 파싱 실패 시
|
|
22
|
+
*/
|
|
23
|
+
export async function handleFetchProblemContentBOJ(args) {
|
|
24
|
+
try {
|
|
25
|
+
// 1. 입력 검증
|
|
26
|
+
const { problem_id } = FetchProblemContentBOJInputSchema.parse(args);
|
|
27
|
+
// 2. BOJ 페이지 스크래핑
|
|
28
|
+
const scraper = new BOJScraper();
|
|
29
|
+
const html = await scraper.fetchProblemPage(problem_id);
|
|
30
|
+
// 3. HTML 파싱
|
|
31
|
+
const content = parseProblemContent(html, problem_id);
|
|
32
|
+
// 4. JSON 문자열로 반환
|
|
33
|
+
return {
|
|
34
|
+
type: 'text',
|
|
35
|
+
text: JSON.stringify(content, null, 2),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// Zod 검증 에러
|
|
40
|
+
if (error instanceof z.ZodError) {
|
|
41
|
+
throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
|
|
42
|
+
}
|
|
43
|
+
// BOJ 스크래핑 에러
|
|
44
|
+
if (error instanceof BojFetchError) {
|
|
45
|
+
if (error.code === 'NOT_FOUND') {
|
|
46
|
+
throw new Error(`문제를 찾을 수 없습니다: ${args.problem_id}번`);
|
|
47
|
+
}
|
|
48
|
+
if (error.code === 'TIMEOUT') {
|
|
49
|
+
throw new Error(`문제 페이지 요청이 타임아웃되었습니다: ${args.problem_id}번`);
|
|
50
|
+
}
|
|
51
|
+
if (error.code === 'NETWORK_ERROR') {
|
|
52
|
+
throw new Error(`네트워크 에러가 발생했습니다: ${error.message}`);
|
|
53
|
+
}
|
|
54
|
+
if (error.code === 'PARSE_ERROR') {
|
|
55
|
+
throw new Error(`문제 페이지 응답을 처리할 수 없습니다: ${error.message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// HTML 파싱 에러
|
|
59
|
+
if (error instanceof HtmlParseError) {
|
|
60
|
+
throw new Error(`HTML 파싱 실패 (${error.field}): ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
// 기타 에러
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* MCP 도구 정의
|
|
68
|
+
*/
|
|
69
|
+
export function fetchProblemContentBOJTool() {
|
|
70
|
+
return {
|
|
71
|
+
name: 'fetch_problem_content_boj',
|
|
72
|
+
description: `백준(BOJ) 문제 본문 스크래핑 (힌트 제외).
|
|
73
|
+
|
|
74
|
+
BOJ 페이지에서 문제 제목, 설명, 입출력 형식, 예제, 제한사항을 가져옵니다.
|
|
75
|
+
**힌트는 포함되지 않습니다** - generate_hint_boj 도구를 사용하세요.
|
|
76
|
+
|
|
77
|
+
응답 구조: problemId, title, description, inputFormat, outputFormat, examples, limits, metadata
|
|
78
|
+
|
|
79
|
+
**사용 시나리오**:
|
|
80
|
+
- 문제 풀이 전 문제 본문 확인
|
|
81
|
+
- 문제 복습 시 문제 내용 참조
|
|
82
|
+
- 코드 분석 시 문제 요구사항 비교
|
|
83
|
+
|
|
84
|
+
**제한사항**:
|
|
85
|
+
- 스크래핑 대상: https://www.acmicpc.net/problem/{problem_id}
|
|
86
|
+
- 타임아웃: 10초
|
|
87
|
+
- 재시도: 최대 2회
|
|
88
|
+
- 캐시: 30일`,
|
|
89
|
+
inputSchema: FetchProblemContentBOJInputSchema,
|
|
90
|
+
handler: handleFetchProblemContentBOJ,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=fetch-problem-content-boj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-problem-content-boj.js","sourceRoot":"","sources":["../../src/tools/fetch-problem-content-boj.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9E;;GAEG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CAAC;IACxD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACpC,QAAQ,CAAC,UAAU,CAAC;CACxB,CAAC,CAAC;AAYH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,IAAa;IAC9D,IAAI,CAAC;QACH,WAAW;QACX,MAAM,EAAE,UAAU,EAAE,GAAG,iCAAiC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAErE,kBAAkB;QAClB,MAAM,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAExD,aAAa;QACb,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEtD,kBAAkB;QAClB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;SACvC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY;QACZ,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,cAAc;QACd,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,kBAAmB,IAAoC,CAAC,UAAU,GAAG,CAAC,CAAC;YACzF,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,yBAA0B,IAAoC,CAAC,UAAU,GAAG,CAAC,CAAC;YAChG,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAED,aAAa;QACb,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,QAAQ;QACR,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE;;;;;;;;;;;;;;;;UAgBP;QACN,WAAW,EAAE,iCAAiC;QAC9C,OAAO,EAAE,4BAA4B;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch_problem_content_programmers MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* 프로그래머스 문제 본문을 ProblemContent 형태로 반환
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { ProgrammersScraper } from '../api/programmers-scraper.js';
|
|
8
|
+
/**
|
|
9
|
+
* 입력 스키마
|
|
10
|
+
*/
|
|
11
|
+
export declare const FetchProblemContentProgrammersInputSchema: z.ZodObject<{
|
|
12
|
+
problem_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
problem_id: string | number;
|
|
15
|
+
}, {
|
|
16
|
+
problem_id: string | number;
|
|
17
|
+
}>;
|
|
18
|
+
export type FetchProblemContentProgrammersInput = z.infer<typeof FetchProblemContentProgrammersInputSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* MCP TextContent 타입
|
|
21
|
+
*/
|
|
22
|
+
interface TextContent {
|
|
23
|
+
type: 'text';
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* fetch_problem_content_programmers 핸들러 (재사용 가능)
|
|
28
|
+
*/
|
|
29
|
+
export declare function handleFetchProblemContentProgrammers(args: unknown, scraper: ProgrammersScraper): Promise<TextContent>;
|
|
30
|
+
/**
|
|
31
|
+
* fetch_problem_content_programmers 도구 핸들러
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchProblemContentProgrammersTool(scraper: ProgrammersScraper): {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
inputSchema: z.ZodObject<{
|
|
37
|
+
problem_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
problem_id: string | number;
|
|
40
|
+
}, {
|
|
41
|
+
problem_id: string | number;
|
|
42
|
+
}>;
|
|
43
|
+
handler: (input: FetchProblemContentProgrammersInput) => Promise<TextContent>;
|
|
44
|
+
};
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=fetch-problem-content-programmers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-problem-content-programmers.d.ts","sourceRoot":"","sources":["../../src/tools/fetch-problem-content-programmers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAKxE;;GAEG;AACH,eAAO,MAAM,yCAAyC;;;;;;EAGpD,CAAC;AAEH,MAAM,MAAM,mCAAmC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yCAAyC,CAAC,CAAC;AAE5G;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,oCAAoC,CACxD,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,kBAAkB;;;;;;;;;;qBAmBzD,mCAAmC;EAGvD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch_problem_content_programmers MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* 프로그래머스 문제 본문을 ProblemContent 형태로 반환
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { ProgrammersScrapeError } from '../api/programmers-scraper.js';
|
|
8
|
+
import { parseProgrammersUrl } from '../utils/url-parser.js';
|
|
9
|
+
import { programmersToProblemContent } from '../utils/programmers-converter.js';
|
|
10
|
+
/**
|
|
11
|
+
* 입력 스키마
|
|
12
|
+
*/
|
|
13
|
+
export const FetchProblemContentProgrammersInputSchema = z.object({
|
|
14
|
+
problem_id: z.union([z.string(), z.number()])
|
|
15
|
+
.describe('프로그래머스 문제 ID 또는 URL'),
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* fetch_problem_content_programmers 핸들러 (재사용 가능)
|
|
19
|
+
*/
|
|
20
|
+
export async function handleFetchProblemContentProgrammers(args, scraper) {
|
|
21
|
+
try {
|
|
22
|
+
const { problem_id } = FetchProblemContentProgrammersInputSchema.parse(args);
|
|
23
|
+
const parsedId = parseProgrammersUrl(problem_id);
|
|
24
|
+
if (!parsedId) {
|
|
25
|
+
throw new Error(`유효하지 않은 프로그래머스 문제 ID 또는 URL: ${problem_id}`);
|
|
26
|
+
}
|
|
27
|
+
const detail = await scraper.getProblem(parsedId);
|
|
28
|
+
const content = programmersToProblemContent(detail);
|
|
29
|
+
return {
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: JSON.stringify(content, null, 2),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof z.ZodError) {
|
|
36
|
+
throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
|
|
37
|
+
}
|
|
38
|
+
if (error instanceof ProgrammersScrapeError) {
|
|
39
|
+
if (error.code === 'NAVIGATION_ERROR') {
|
|
40
|
+
throw new Error(`문제를 찾을 수 없습니다: ${args.problem_id}`);
|
|
41
|
+
}
|
|
42
|
+
if (error.code === 'TIMEOUT') {
|
|
43
|
+
throw new Error(`요청이 타임아웃되었습니다: ${args.problem_id}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* fetch_problem_content_programmers 도구 핸들러
|
|
51
|
+
*/
|
|
52
|
+
export function fetchProblemContentProgrammersTool(scraper) {
|
|
53
|
+
return {
|
|
54
|
+
name: 'fetch_problem_content_programmers',
|
|
55
|
+
description: `프로그래머스 문제 본문 스크래핑.
|
|
56
|
+
|
|
57
|
+
프로그래머스 페이지에서 문제 제목, 설명, 제한사항, 입출력 예시를 가져옵니다.
|
|
58
|
+
|
|
59
|
+
응답 구조: problemId, title, description, inputFormat, outputFormat, examples, limits, metadata
|
|
60
|
+
|
|
61
|
+
**사용 시나리오**:
|
|
62
|
+
- 문제 풀이 전 문제 본문 확인
|
|
63
|
+
- 코드 분석 시 문제 요구사항 비교
|
|
64
|
+
|
|
65
|
+
**제한사항**:
|
|
66
|
+
- 스크래핑 대상: https://school.programmers.co.kr/learn/courses/30/lessons/{problem_id}
|
|
67
|
+
- 타임아웃: 10초
|
|
68
|
+
- 재시도: 최대 2회
|
|
69
|
+
- 캐시: 30일`,
|
|
70
|
+
inputSchema: FetchProblemContentProgrammersInputSchema,
|
|
71
|
+
handler: (input) => handleFetchProblemContentProgrammers(input, scraper),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=fetch-problem-content-programmers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-problem-content-programmers.js","sourceRoot":"","sources":["../../src/tools/fetch-problem-content-programmers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,yCAAyC,GAAG,CAAC,CAAC,MAAM,CAAC;IAChE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;SAC1C,QAAQ,CAAC,qBAAqB,CAAC;CACnC,CAAC,CAAC;AAYH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oCAAoC,CACxD,IAAa,EACb,OAA2B;IAE3B,IAAI,CAAC;QACH,MAAM,EAAE,UAAU,EAAE,GAAG,yCAAyC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,gCAAgC,UAAU,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;QAEpD,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;SACvC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;YAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CAAC,kBAAmB,IAA4C,CAAC,UAAU,EAAE,CAAC,CAAC;YAChG,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,kBAAmB,IAA4C,CAAC,UAAU,EAAE,CAAC,CAAC;YAChG,CAAC;QACH,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kCAAkC,CAAC,OAA2B;IAC5E,OAAO;QACL,IAAI,EAAE,mCAAmC;QACzC,WAAW,EAAE;;;;;;;;;;;;;;UAcP;QACN,WAAW,EAAE,yCAAyC;QACtD,OAAO,EAAE,CAAC,KAA0C,EAAE,EAAE,CACtD,oCAAoC,CAAC,KAAK,EAAE,OAAO,CAAC;KACvD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch_problem_content MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* Phase 6 - P6-004: BOJ 문제 본문 스크래핑 MCP 도구 구현
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
/**
|
|
8
|
+
* 입력 스키마
|
|
9
|
+
*/
|
|
10
|
+
export declare const FetchProblemContentInputSchema: z.ZodObject<{
|
|
11
|
+
problem_id: z.ZodNumber;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
problem_id: number;
|
|
14
|
+
}, {
|
|
15
|
+
problem_id: number;
|
|
16
|
+
}>;
|
|
17
|
+
export type FetchProblemContentInput = z.infer<typeof FetchProblemContentInputSchema>;
|
|
18
|
+
/**
|
|
19
|
+
* MCP TextContent 타입
|
|
20
|
+
*/
|
|
21
|
+
interface TextContent {
|
|
22
|
+
type: 'text';
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* fetch_problem_content 도구 핸들러
|
|
27
|
+
*
|
|
28
|
+
* @param args - 입력 인자 (problem_id)
|
|
29
|
+
* @returns ProblemContent JSON 문자열
|
|
30
|
+
* @throws {Error} 검증 실패, 스크래핑 실패, 파싱 실패 시
|
|
31
|
+
*/
|
|
32
|
+
export declare function handleFetchProblemContent(args: unknown): Promise<TextContent>;
|
|
33
|
+
/**
|
|
34
|
+
* MCP 도구 정의
|
|
35
|
+
*/
|
|
36
|
+
export declare function fetchProblemContentTool(): {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
inputSchema: z.ZodObject<{
|
|
40
|
+
problem_id: z.ZodNumber;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
problem_id: number;
|
|
43
|
+
}, {
|
|
44
|
+
problem_id: number;
|
|
45
|
+
}>;
|
|
46
|
+
handler: typeof handleFetchProblemContent;
|
|
47
|
+
};
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=fetch-problem-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-problem-content.d.ts","sourceRoot":"","sources":["../../src/tools/fetch-problem-content.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;GAEG;AACH,eAAO,MAAM,8BAA8B;;;;;;EAGzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA+CnF;AAED;;GAEG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;EAuBtC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fetch_problem_content MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* Phase 6 - P6-004: BOJ 문제 본문 스크래핑 MCP 도구 구현
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { BOJScraper, BojFetchError } from '../api/boj-scraper.js';
|
|
8
|
+
import { parseProblemContent, HtmlParseError } from '../utils/html-parser.js';
|
|
9
|
+
/**
|
|
10
|
+
* 입력 스키마
|
|
11
|
+
*/
|
|
12
|
+
export const FetchProblemContentInputSchema = z.object({
|
|
13
|
+
problem_id: z.number().int().positive()
|
|
14
|
+
.describe('백준 문제 번호'),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* fetch_problem_content 도구 핸들러
|
|
18
|
+
*
|
|
19
|
+
* @param args - 입력 인자 (problem_id)
|
|
20
|
+
* @returns ProblemContent JSON 문자열
|
|
21
|
+
* @throws {Error} 검증 실패, 스크래핑 실패, 파싱 실패 시
|
|
22
|
+
*/
|
|
23
|
+
export async function handleFetchProblemContent(args) {
|
|
24
|
+
try {
|
|
25
|
+
// 1. 입력 검증
|
|
26
|
+
const { problem_id } = FetchProblemContentInputSchema.parse(args);
|
|
27
|
+
// 2. BOJ 페이지 스크래핑
|
|
28
|
+
const scraper = new BOJScraper();
|
|
29
|
+
const html = await scraper.fetchProblemPage(problem_id);
|
|
30
|
+
// 3. HTML 파싱
|
|
31
|
+
const content = parseProblemContent(html, problem_id);
|
|
32
|
+
// 4. JSON 문자열로 반환
|
|
33
|
+
return {
|
|
34
|
+
type: 'text',
|
|
35
|
+
text: JSON.stringify(content, null, 2),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// Zod 검증 에러
|
|
40
|
+
if (error instanceof z.ZodError) {
|
|
41
|
+
throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
|
|
42
|
+
}
|
|
43
|
+
// BOJ 스크래핑 에러
|
|
44
|
+
if (error instanceof BojFetchError) {
|
|
45
|
+
if (error.code === 'NOT_FOUND') {
|
|
46
|
+
throw new Error(`문제를 찾을 수 없습니다: ${args.problem_id}번`);
|
|
47
|
+
}
|
|
48
|
+
if (error.code === 'TIMEOUT') {
|
|
49
|
+
throw new Error(`문제 페이지 요청이 타임아웃되었습니다: ${args.problem_id}번`);
|
|
50
|
+
}
|
|
51
|
+
if (error.code === 'NETWORK_ERROR') {
|
|
52
|
+
throw new Error(`네트워크 에러가 발생했습니다: ${error.message}`);
|
|
53
|
+
}
|
|
54
|
+
if (error.code === 'PARSE_ERROR') {
|
|
55
|
+
throw new Error(`문제 페이지 응답을 처리할 수 없습니다: ${error.message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// HTML 파싱 에러
|
|
59
|
+
if (error instanceof HtmlParseError) {
|
|
60
|
+
throw new Error(`HTML 파싱 실패 (${error.field}): ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
// 기타 에러
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* MCP 도구 정의
|
|
68
|
+
*/
|
|
69
|
+
export function fetchProblemContentTool() {
|
|
70
|
+
return {
|
|
71
|
+
name: 'fetch_problem_content',
|
|
72
|
+
description: `백준 문제 본문 스크래핑 (힌트 제외).
|
|
73
|
+
|
|
74
|
+
BOJ 페이지에서 문제 제목, 설명, 입출력 형식, 예제, 제한사항을 가져옵니다.
|
|
75
|
+
**힌트는 포함되지 않습니다** - generate_hint 도구를 사용하세요.
|
|
76
|
+
|
|
77
|
+
응답 구조: problemId, title, description, inputFormat, outputFormat, examples, limits, metadata
|
|
78
|
+
|
|
79
|
+
**사용 시나리오**:
|
|
80
|
+
- 문제 풀이 전 문제 본문 확인
|
|
81
|
+
- 문제 복습 시 문제 내용 참조
|
|
82
|
+
- 코드 분석 시 문제 요구사항 비교
|
|
83
|
+
|
|
84
|
+
**제한사항**:
|
|
85
|
+
- 스크래핑 대상: https://www.acmicpc.net/problem/{problem_id}
|
|
86
|
+
- 타임아웃: 10초
|
|
87
|
+
- 재시도: 최대 2회
|
|
88
|
+
- 캐시: 30일 (Phase 6-3에서 구현 예정)`,
|
|
89
|
+
inputSchema: FetchProblemContentInputSchema,
|
|
90
|
+
handler: handleFetchProblemContent,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=fetch-problem-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-problem-content.js","sourceRoot":"","sources":["../../src/tools/fetch-problem-content.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9E;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACpC,QAAQ,CAAC,UAAU,CAAC;CACxB,CAAC,CAAC;AAYH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAAa;IAC3D,IAAI,CAAC;QACH,WAAW;QACX,MAAM,EAAE,UAAU,EAAE,GAAG,8BAA8B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElE,kBAAkB;QAClB,MAAM,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAExD,aAAa;QACb,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEtD,kBAAkB;QAClB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;SACvC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY;QACZ,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,cAAc;QACd,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,kBAAmB,IAAiC,CAAC,UAAU,GAAG,CAAC,CAAC;YACtF,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,yBAA0B,IAAiC,CAAC,UAAU,GAAG,CAAC,CAAC;YAC7F,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAED,aAAa;QACb,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,QAAQ;QACR,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE;;;;;;;;;;;;;;;;8BAgBa;QAC1B,WAAW,EAAE,8BAA8B;QAC3C,OAAO,EAAE,yBAAyB;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_hint_boj MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* BOJ 문제 힌트 가이드 생성 (SRP: 힌트만)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { ProblemAnalyzer } from '../services/problem-analyzer.js';
|
|
8
|
+
/**
|
|
9
|
+
* 입력 스키마
|
|
10
|
+
*/
|
|
11
|
+
export declare const GenerateHintBOJInputSchema: z.ZodObject<{
|
|
12
|
+
problem_id: z.ZodNumber;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
problem_id: number;
|
|
15
|
+
}, {
|
|
16
|
+
problem_id: number;
|
|
17
|
+
}>;
|
|
18
|
+
export type GenerateHintBOJInput = z.infer<typeof GenerateHintBOJInputSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* MCP TextContent 타입
|
|
21
|
+
*/
|
|
22
|
+
interface TextContent {
|
|
23
|
+
type: 'text';
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* generate-hint 도구 핸들러
|
|
28
|
+
*/
|
|
29
|
+
export declare function generateHintBOJTool(analyzer: ProblemAnalyzer): {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
inputSchema: z.ZodObject<{
|
|
33
|
+
problem_id: z.ZodNumber;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
problem_id: number;
|
|
36
|
+
}, {
|
|
37
|
+
problem_id: number;
|
|
38
|
+
}>;
|
|
39
|
+
handler: (input: GenerateHintBOJInput) => Promise<TextContent>;
|
|
40
|
+
};
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=generate-hint-boj.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-hint-boj.d.ts","sourceRoot":"","sources":["../../src/tools/generate-hint-boj.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;EAGrC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe;;;;;;;;;;qBAmClC,oBAAoB,KAAG,OAAO,CAAC,WAAW,CAAC;EA6BrE"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_hint_boj MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* BOJ 문제 힌트 가이드 생성 (SRP: 힌트만)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { ProblemNotFoundError } from '../api/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* 입력 스키마
|
|
10
|
+
*/
|
|
11
|
+
export const GenerateHintBOJInputSchema = z.object({
|
|
12
|
+
problem_id: z.number().int().positive()
|
|
13
|
+
.describe('백준 문제 번호'),
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* generate-hint 도구 핸들러
|
|
17
|
+
*/
|
|
18
|
+
export function generateHintBOJTool(analyzer) {
|
|
19
|
+
return {
|
|
20
|
+
name: 'generate_hint_boj',
|
|
21
|
+
description: `백준(BOJ) 문제 힌트 생성. 3단계 가이드 프롬프트 제공.
|
|
22
|
+
|
|
23
|
+
🎯 **핵심: 한 번에 1개 레벨 힌트만 제공. 1,2,3 단계를 동시에 제시하지 마세요.**
|
|
24
|
+
|
|
25
|
+
📋 응답에 포함된 정보:
|
|
26
|
+
- hint_levels[0]: Level 1 - 문제 분석 (처음 시도)
|
|
27
|
+
- hint_levels[1]: Level 2 - 핵심 아이디어 (부분 구현)
|
|
28
|
+
- hint_levels[2]: Level 3 - 상세 풀이 (거의 완성)
|
|
29
|
+
|
|
30
|
+
🤖 **사용자 상황 판단 → 적절한 1개 레벨만 제시**:
|
|
31
|
+
|
|
32
|
+
1️⃣ Level 1 제시 (처음/막힐 때):
|
|
33
|
+
"사용자가 코드 없거나 어디서부터 시작해야 할지 모를 때"
|
|
34
|
+
→ hint_levels[0].prompt로 문제 접근법 제시
|
|
35
|
+
|
|
36
|
+
2️⃣ Level 2 제시 (다시 요청하거나 부분 구현 언급):
|
|
37
|
+
"사용자가 '더 필요해', '더 자세히' 요청하거나, 이미 코드를 시작했다고 언급"
|
|
38
|
+
→ hint_levels[1].prompt로 핵심 로직 제시
|
|
39
|
+
|
|
40
|
+
3️⃣ Level 3 제시 (상세 풀이 명시 요청):
|
|
41
|
+
"사용자가 '정답', '풀이', '코드' 등 최종 답변 요청"
|
|
42
|
+
→ hint_levels[2].prompt로 상세 구현 가이드 제시
|
|
43
|
+
|
|
44
|
+
📖 **[권장] 어려운 문제는 본문 먼저 확인**:
|
|
45
|
+
- 난이도 높은 문제(Gold 이상, level ≥ 11)는 메타데이터만으로 부족할 수 있음
|
|
46
|
+
- fetch_problem_content로 실제 문제 본문 확인 후 힌트 생성 권장
|
|
47
|
+
- 문제 본문을 보면 더 정확하고 맞춤형 힌트 제공 가능
|
|
48
|
+
- 예: mcp-cli call algokit/fetch_problem_content '{"problem_id": 1234}'
|
|
49
|
+
- 본문 확인은 권장사항이며 필수는 아님
|
|
50
|
+
|
|
51
|
+
**정답 정책**: 힌트만 기본 제공. 사용자가 "정답", "풀이", "코드" 명시 요청 시만 전체 풀이 제공.`,
|
|
52
|
+
inputSchema: GenerateHintBOJInputSchema,
|
|
53
|
+
handler: async (input) => {
|
|
54
|
+
try {
|
|
55
|
+
// 입력 검증
|
|
56
|
+
const { problem_id } = GenerateHintBOJInputSchema.parse(input);
|
|
57
|
+
// 힌트 가이드 생성 (유사 문제 제외)
|
|
58
|
+
const result = await analyzer.analyze(problem_id, false);
|
|
59
|
+
// JSON 문자열로 반환 (Claude Code가 파싱)
|
|
60
|
+
return {
|
|
61
|
+
type: 'text',
|
|
62
|
+
text: JSON.stringify(result, null, 2),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
// Zod 검증 에러
|
|
67
|
+
if (error instanceof z.ZodError) {
|
|
68
|
+
throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
|
|
69
|
+
}
|
|
70
|
+
// ProblemNotFoundError
|
|
71
|
+
if (error instanceof ProblemNotFoundError) {
|
|
72
|
+
throw new Error(`문제를 찾을 수 없습니다: ${input.problem_id}번`);
|
|
73
|
+
}
|
|
74
|
+
// 기타 에러
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=generate-hint-boj.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-hint-boj.js","sourceRoot":"","sources":["../../src/tools/generate-hint-boj.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACpC,QAAQ,CAAC,UAAU,CAAC;CACxB,CAAC,CAAC;AAYH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAyB;IAC3D,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA8B8C;QAC3D,WAAW,EAAE,0BAA0B;QACvC,OAAO,EAAE,KAAK,EAAE,KAA2B,EAAwB,EAAE;YACnE,IAAI,CAAC;gBACH,QAAQ;gBACR,MAAM,EAAE,UAAU,EAAE,GAAG,0BAA0B,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAE/D,uBAAuB;gBACvB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBAEzD,iCAAiC;gBACjC,OAAO;oBACL,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;iBACtC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,YAAY;gBACZ,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC1D,CAAC;gBAED,uBAAuB;gBACvB,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;oBAC1C,MAAM,IAAI,KAAK,CAAC,kBAAmB,KAA8B,CAAC,UAAU,GAAG,CAAC,CAAC;gBACnF,CAAC;gBAED,QAAQ;gBACR,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_hint_programmers MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* 프로그래머스 문제 힌트 가이드 생성 (SRP: 힌트만)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { ProgrammersProblemAnalyzer } from '../services/programmers-problem-analyzer.js';
|
|
8
|
+
/**
|
|
9
|
+
* 입력 스키마
|
|
10
|
+
*/
|
|
11
|
+
export declare const GenerateHintProgrammersInputSchema: z.ZodObject<{
|
|
12
|
+
problem_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
problem_id: string | number;
|
|
15
|
+
}, {
|
|
16
|
+
problem_id: string | number;
|
|
17
|
+
}>;
|
|
18
|
+
export type GenerateHintProgrammersInput = z.infer<typeof GenerateHintProgrammersInputSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* MCP TextContent 타입
|
|
21
|
+
*/
|
|
22
|
+
interface TextContent {
|
|
23
|
+
type: 'text';
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* generate_hint_programmers 도구 핸들러
|
|
28
|
+
*/
|
|
29
|
+
export declare function generateHintProgrammersTool(analyzer: ProgrammersProblemAnalyzer): {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
inputSchema: z.ZodObject<{
|
|
33
|
+
problem_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
problem_id: string | number;
|
|
36
|
+
}, {
|
|
37
|
+
problem_id: string | number;
|
|
38
|
+
}>;
|
|
39
|
+
handler: (input: GenerateHintProgrammersInput) => Promise<TextContent>;
|
|
40
|
+
};
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=generate-hint-programmers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-hint-programmers.d.ts","sourceRoot":"","sources":["../../src/tools/generate-hint-programmers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AAI9F;;GAEG;AACH,eAAO,MAAM,kCAAkC;;;;;;EAG7C,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,0BAA0B;;;;;;;;;;qBAgCrD,4BAA4B,KAAG,OAAO,CAAC,WAAW,CAAC;EA8B7E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generate_hint_programmers MCP 도구
|
|
3
|
+
*
|
|
4
|
+
* 프로그래머스 문제 힌트 가이드 생성 (SRP: 힌트만)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { ProgrammersScrapeError } from '../api/programmers-scraper.js';
|
|
8
|
+
import { parseProgrammersUrl } from '../utils/url-parser.js';
|
|
9
|
+
/**
|
|
10
|
+
* 입력 스키마
|
|
11
|
+
*/
|
|
12
|
+
export const GenerateHintProgrammersInputSchema = z.object({
|
|
13
|
+
problem_id: z.union([z.string(), z.number()])
|
|
14
|
+
.describe('프로그래머스 문제 ID 또는 URL'),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* generate_hint_programmers 도구 핸들러
|
|
18
|
+
*/
|
|
19
|
+
export function generateHintProgrammersTool(analyzer) {
|
|
20
|
+
return {
|
|
21
|
+
name: 'generate_hint_programmers',
|
|
22
|
+
description: `프로그래머스 문제 힌트 생성. 3단계 가이드 프롬프트 제공.
|
|
23
|
+
|
|
24
|
+
🎯 **핵심: 한 번에 1개 레벨 힌트만 제공. 1,2,3 단계를 동시에 제시하지 마세요.**
|
|
25
|
+
|
|
26
|
+
📋 응답에 포함된 정보:
|
|
27
|
+
- hint_levels[0]: Level 1 - 문제 분석 (처음 시도)
|
|
28
|
+
- hint_levels[1]: Level 2 - 핵심 아이디어 (부분 구현)
|
|
29
|
+
- hint_levels[2]: Level 3 - 상세 풀이 (거의 완성)
|
|
30
|
+
|
|
31
|
+
🤖 **사용자 상황 판단 → 적절한 1개 레벨만 제시**:
|
|
32
|
+
|
|
33
|
+
1️⃣ Level 1 제시 (처음/막힐 때):
|
|
34
|
+
"사용자가 코드 없거나 어디서부터 시작해야 할지 모를 때"
|
|
35
|
+
→ hint_levels[0].prompt로 문제 접근법 제시
|
|
36
|
+
|
|
37
|
+
2️⃣ Level 2 제시 (다시 요청하거나 부분 구현 언급):
|
|
38
|
+
"사용자가 '더 필요해', '더 자세히' 요청하거나, 이미 코드를 시작했다고 언급"
|
|
39
|
+
→ hint_levels[1].prompt로 핵심 로직 제시
|
|
40
|
+
|
|
41
|
+
3️⃣ Level 3 제시 (상세 풀이 명시 요청):
|
|
42
|
+
"사용자가 '정답', '풀이', '코드' 등 최종 답변 요청"
|
|
43
|
+
→ hint_levels[2].prompt로 상세 구현 가이드 제시
|
|
44
|
+
|
|
45
|
+
📖 **[권장] 어려운 문제는 본문 먼저 확인**:
|
|
46
|
+
- 난이도 높은 문제(Lv. 3 이상)는 메타데이터만으로 부족할 수 있음
|
|
47
|
+
- fetch_problem_content_programmers로 실제 문제 본문 확인 후 힌트 생성 권장
|
|
48
|
+
|
|
49
|
+
**정답 정책**: 힌트만 기본 제공. 사용자가 "정답", "풀이", "코드" 명시 요청 시만 전체 풀이 제공.`,
|
|
50
|
+
inputSchema: GenerateHintProgrammersInputSchema,
|
|
51
|
+
handler: async (input) => {
|
|
52
|
+
try {
|
|
53
|
+
const { problem_id } = GenerateHintProgrammersInputSchema.parse(input);
|
|
54
|
+
const parsedId = parseProgrammersUrl(problem_id);
|
|
55
|
+
if (!parsedId) {
|
|
56
|
+
throw new Error(`유효하지 않은 프로그래머스 문제 ID 또는 URL: ${problem_id}`);
|
|
57
|
+
}
|
|
58
|
+
const result = await analyzer.analyze(parsedId, false);
|
|
59
|
+
return {
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: JSON.stringify(result, null, 2),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error instanceof z.ZodError) {
|
|
66
|
+
throw new Error(`입력 검증 실패: ${error.issues[0].message}`);
|
|
67
|
+
}
|
|
68
|
+
if (error instanceof ProgrammersScrapeError) {
|
|
69
|
+
if (error.code === 'NAVIGATION_ERROR') {
|
|
70
|
+
throw new Error(`문제를 찾을 수 없습니다: ${input.problem_id}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=generate-hint-programmers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-hint-programmers.js","sourceRoot":"","sources":["../../src/tools/generate-hint-programmers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;GAEG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;SAC1C,QAAQ,CAAC,qBAAqB,CAAC;CACnC,CAAC,CAAC;AAYH;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,QAAoC;IAC9E,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA2B8C;QAC3D,WAAW,EAAE,kCAAkC;QAC/C,OAAO,EAAE,KAAK,EAAE,KAAmC,EAAwB,EAAE;YAC3E,IAAI,CAAC;gBACH,MAAM,EAAE,UAAU,EAAE,GAAG,kCAAkC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAEvE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;gBACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CAAC,gCAAgC,UAAU,EAAE,CAAC,CAAC;gBAChE,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAEvD,OAAO;oBACL,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;iBACtC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC1D,CAAC;gBAED,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;oBAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBACtC,MAAM,IAAI,KAAK,CAAC,kBAAmB,KAAsC,CAAC,UAAU,EAAE,CAAC,CAAC;oBAC1F,CAAC;gBACH,CAAC;gBAED,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|