@noesis-brain/mcp-server 2.1.1 → 2.1.2

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.
@@ -0,0 +1,89 @@
1
+ /**
2
+ * ExamData shape accepted by the backend's POST /api/notes/from-exam.
3
+ *
4
+ * Ported from the frontend repo's
5
+ * src/frontend/src/components/Chat/tools/exam/types.ts — kept as a verbatim
6
+ * copy (zero external imports there, so this is safe) rather than shared via
7
+ * a package, since the MCP server is a separate git repo/npm package with no
8
+ * dependency path to the frontend. Keep in sync by hand if the frontend
9
+ * shape changes; the backend's validateExamData
10
+ * (src/backend/services/examSources/examDataValidator.ts) is the real,
11
+ * authoritative gate either way.
12
+ */
13
+ export interface TranslationQuestion {
14
+ type: 'translation';
15
+ id: string;
16
+ questionNum: number;
17
+ zhPrompt: string;
18
+ answerEn: string;
19
+ sourceWord?: string;
20
+ }
21
+ export interface SentenceCompletionQuestion {
22
+ type: 'sentence-completion';
23
+ id: string;
24
+ questionNum: number;
25
+ sentenceWithBlank: string;
26
+ choices: string[];
27
+ correctIndex: number;
28
+ sourceWord?: string;
29
+ }
30
+ export interface VocabInContextQuestion {
31
+ type: 'vocab-in-context';
32
+ id: string;
33
+ questionNum: number;
34
+ sentence: string;
35
+ underlinedWord: string;
36
+ choices: string[];
37
+ correctIndex: number;
38
+ sourceWord?: string;
39
+ }
40
+ export interface MultipleChoiceQuestion {
41
+ type: 'multiple-choice';
42
+ id: string;
43
+ questionNum: number;
44
+ prompt: string;
45
+ choices: string[];
46
+ correctIndex: number;
47
+ explanation?: string;
48
+ }
49
+ export interface CalculationQuestion {
50
+ type: 'calculation';
51
+ id: string;
52
+ questionNum: number;
53
+ prompt: string;
54
+ answer: string;
55
+ acceptedForms?: string[];
56
+ tolerance?: number;
57
+ unit?: string;
58
+ explanation?: string;
59
+ }
60
+ export interface ShortAnswerQuestion {
61
+ type: 'short-answer';
62
+ id: string;
63
+ questionNum: number;
64
+ prompt: string;
65
+ referenceAnswer: string;
66
+ rubric?: string;
67
+ }
68
+ export interface FillInBlankQuestion {
69
+ type: 'fill-in-the-blank';
70
+ id: string;
71
+ questionNum: number;
72
+ prompt: string;
73
+ answer: string;
74
+ acceptedForms?: string[];
75
+ }
76
+ export type ExamQuestion = TranslationQuestion | SentenceCompletionQuestion | VocabInContextQuestion | MultipleChoiceQuestion | CalculationQuestion | ShortAnswerQuestion | FillInBlankQuestion;
77
+ export interface ExamSection {
78
+ title: string;
79
+ instructions: string;
80
+ points: number;
81
+ questions: ExamQuestion[];
82
+ }
83
+ export interface ExamData {
84
+ title: string;
85
+ date: string;
86
+ sections: ExamSection[];
87
+ totalPoints: number;
88
+ }
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tools/exam/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,kBAAkB,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,iBAAiB,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,YAAY,GACpB,mBAAmB,GACnB,0BAA0B,GAC1B,sBAAsB,GACtB,sBAAsB,GACtB,mBAAmB,GACnB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ExamData shape accepted by the backend's POST /api/notes/from-exam.
3
+ *
4
+ * Ported from the frontend repo's
5
+ * src/frontend/src/components/Chat/tools/exam/types.ts — kept as a verbatim
6
+ * copy (zero external imports there, so this is safe) rather than shared via
7
+ * a package, since the MCP server is a separate git repo/npm package with no
8
+ * dependency path to the frontend. Keep in sync by hand if the frontend
9
+ * shape changes; the backend's validateExamData
10
+ * (src/backend/services/examSources/examDataValidator.ts) is the real,
11
+ * authoritative gate either way.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/tools/exam/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Exam creation tool for the md-manager MCP server.
3
+ *
4
+ * Creates a real, DB-backed exam note (fillable answer markers, hidden answer
5
+ * key, gradeable via the app's own grading pipeline) from a hand-authored
6
+ * ExamData object — the same shape the app's AI exam generator produces, so
7
+ * the resulting note is indistinguishable from one created in-app.
8
+ */
9
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
+ import type { NoesisClient } from '../api/NoesisClient.js';
11
+ export declare function registerExamTools(server: McpServer, client: NoesisClient): void;
12
+ //# sourceMappingURL=exam.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exam.d.ts","sourceRoot":"","sources":["../../src/tools/exam.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAuB3D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAuB/E"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Exam creation tool for the md-manager MCP server.
3
+ *
4
+ * Creates a real, DB-backed exam note (fillable answer markers, hidden answer
5
+ * key, gradeable via the app's own grading pipeline) from a hand-authored
6
+ * ExamData object — the same shape the app's AI exam generator produces, so
7
+ * the resulting note is indistinguishable from one created in-app.
8
+ */
9
+ import { z } from 'zod';
10
+ // Top-level shape is strongly typed; sections[].questions[] is intentionally
11
+ // loose (z.record(z.any())) rather than re-encoding the 7-question-type
12
+ // discriminated union a third time (it already lives in the frontend's
13
+ // types.ts and the backend's examDataValidator.ts) — the backend's
14
+ // validateExamData is the real gate and feedback loop (a malformed shape
15
+ // comes back as a descriptive error with a retry hint, not a silent failure).
16
+ const examSectionShape = z.object({
17
+ title: z.string().describe('Section heading, e.g. "Technical Architecture"'),
18
+ instructions: z.string().describe('One-line instructions shown under the section heading'),
19
+ points: z.number().describe('Total points for this section (individual questions do not carry their own point value)'),
20
+ questions: z.array(z.record(z.any())).min(1).describe('Array of question objects. Each needs at minimum {type, id, questionNum}. ' +
21
+ 'Supported types: translation {zhPrompt, answerEn}, sentence-completion {sentenceWithBlank, choices[], correctIndex}, ' +
22
+ 'vocab-in-context {sentence, underlinedWord, choices[], correctIndex}, multiple-choice {prompt, choices[], correctIndex}, ' +
23
+ 'calculation {prompt, answer, acceptedForms?, tolerance?, unit?}, short-answer {prompt, referenceAnswer, rubric?}, ' +
24
+ 'fill-in-the-blank {prompt (with "____" placeholders), answer, acceptedForms?}. ' +
25
+ 'Question ids must be unique across the whole exam.'),
26
+ });
27
+ export function registerExamTools(server, client) {
28
+ // ─── create_exam_note ────────────────────────────────────────
29
+ server.tool('create_exam_note', 'Create a real, DB-backed exam note — fillable answer-marker boxes at each question, a hidden answer key, and gradeable via the app\'s own grading pipeline (POST /:id/exam/grade). This is the actual "exam" note type the app recognizes (NoteTypeBadge, grading UI) — not just markdown that looks like one. On a malformed examData, returns a descriptive error including a retry hint; fix the shape and call again.', {
30
+ title: z.string().describe('Exam title, shown as the note\'s H1 heading'),
31
+ date: z.string().describe('Date string shown under the title, e.g. "2026-07-31"'),
32
+ totalPoints: z.number().describe('Must equal the sum of all sections\' points'),
33
+ sections: z.array(examSectionShape).min(1).describe('At least one section, each with at least one question'),
34
+ }, async (args) => {
35
+ const examData = args;
36
+ const result = await client.createExamFromData(examData);
37
+ const questionCount = Object.keys(result.questionMarks).length;
38
+ return {
39
+ content: [{
40
+ type: 'text',
41
+ text: `Created exam note #${result.noteId}: "${examData.title}" (${examData.totalPoints} points, ${questionCount} question${questionCount === 1 ? '' : 's'} across ${examData.sections.length} section${examData.sections.length === 1 ? '' : 's'}). Fillable answer markers and the hidden answer key are already in place — open the note in the app to answer, then grade via the app's exam UI (or POST /api/notes/${result.noteId}/exam/grade).`
42
+ }]
43
+ };
44
+ });
45
+ }
46
+ //# sourceMappingURL=exam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exam.js","sourceRoot":"","sources":["../../src/tools/exam.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,6EAA6E;AAC7E,wEAAwE;AACxE,uEAAuE;AACvE,mEAAmE;AACnE,yEAAyE;AACzE,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;IAC5E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;IAC1F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yFAAyF,CAAC;IACtH,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CACnD,4EAA4E;QAC5E,uHAAuH;QACvH,2HAA2H;QAC3H,oHAAoH;QACpH,iFAAiF;QACjF,oDAAoD,CACrD;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAoB;IACvE,gEAAgE;IAChE,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,2ZAA2Z,EAC3Z;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QACzE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;QACjF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QAC/E,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uDAAuD,CAAC;KAC7G,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,IAAgB,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QAC/D,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,sBAAsB,MAAM,CAAC,MAAM,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,WAAW,YAAY,aAAa,YAAY,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,QAAQ,CAAC,QAAQ,CAAC,MAAM,WAAW,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,wKAAwK,MAAM,CAAC,MAAM,eAAe;iBACtb,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAyC,KAAK,IAAI,EAA2D,MAAM,wBAAwB,CAAC;AAqIjK;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1C;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAejD;AAqBD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CA44F7E;AA0DD;;;;GAIG;AACH,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAYxF;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,YAAY,EACpB,KAAK,GAAE,OAAe,EACtB,kBAAkB,GAAE,OAAe,GAClC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAigBhF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAI9F;AA+DD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACrE,MAAM,CA2FR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAqBA;AA4SD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAY/E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAyC,KAAK,IAAI,EAA2D,MAAM,wBAAwB,CAAC;AAsIjK;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1C;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAejD;AAqBD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CA64F7E;AA0DD;;;;GAIG;AACH,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAYxF;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EAAE,EACnB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,YAAY,EACpB,KAAK,GAAE,OAAe,EACtB,kBAAkB,GAAE,OAAe,GAClC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAigBhF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAI9F;AA+DD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACrE,MAAM,CA2FR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAqBA;AA4SD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAY/E"}
@@ -13,6 +13,7 @@ import { initEmbeddingService, generateEmbedding, generateEmbeddingsBatch } from
13
13
  import { SyncStateManager, determineSyncDirection } from './SyncStateManager.js';
14
14
  import { registerNaviTools } from './navis.js';
15
15
  import { registerBacklogTools } from './backlog.js';
16
+ import { registerExamTools } from './exam.js';
16
17
  import { suggestOtherOsPath } from '../utils/suggestPath.js';
17
18
  import { diff3Merge, diffPatch } from 'node-diff3';
18
19
  // ============================================
@@ -185,6 +186,7 @@ export function registerTools(server, services) {
185
186
  // Register Navi management tools
186
187
  registerNaviTools(server, client);
187
188
  registerBacklogTools(server, client);
189
+ registerExamTools(server, client);
188
190
  // Register search_notes tool
189
191
  server.tool('search_notes', 'Search your knowledge base using full-text search. Returns relevant notes ranked by BM25 relevance.', {
190
192
  query: z.string().describe('Search query (natural language or keywords)'),