@noesis-brain/mcp-server 2.1.0 → 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.
- package/dist/agent/runner.d.ts +10 -0
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +115 -12
- package/dist/agent/runner.js.map +1 -1
- package/dist/api/NoesisClient.d.ts +19 -0
- package/dist/api/NoesisClient.d.ts.map +1 -1
- package/dist/api/NoesisClient.js +44 -0
- package/dist/api/NoesisClient.js.map +1 -1
- package/dist/tools/backlog.d.ts.map +1 -1
- package/dist/tools/backlog.js +11 -7
- package/dist/tools/backlog.js.map +1 -1
- package/dist/tools/exam/examNoteTemplate.d.ts +32 -0
- package/dist/tools/exam/examNoteTemplate.d.ts.map +1 -0
- package/dist/tools/exam/examNoteTemplate.js +110 -0
- package/dist/tools/exam/examNoteTemplate.js.map +1 -0
- package/dist/tools/exam/types.d.ts +89 -0
- package/dist/tools/exam/types.d.ts.map +1 -0
- package/dist/tools/exam/types.js +14 -0
- package/dist/tools/exam/types.js.map +1 -0
- package/dist/tools/exam.d.ts +12 -0
- package/dist/tools/exam.d.ts.map +1 -0
- package/dist/tools/exam.js +46 -0
- package/dist/tools/exam.js.map +1 -0
- package/dist/tools/index.d.ts +40 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +98 -70
- package/dist/tools/index.js.map +1 -1
- package/package.json +3 -2
- package/scripts/noesis-capture-watcher.mjs +51 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backlog.js","sourceRoot":"","sources":["../../src/tools/backlog.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"backlog.js","sourceRoot":"","sources":["../../src/tools/backlog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ported from the frontend repo's
|
|
3
|
+
* src/frontend/src/components/Chat/tools/exam/examNoteTemplate.ts — kept as a
|
|
4
|
+
* verbatim copy (pure functions, zero external deps) rather than shared via a
|
|
5
|
+
* package, since the MCP server is a separate git repo/npm package with no
|
|
6
|
+
* dependency path to the frontend.
|
|
7
|
+
*
|
|
8
|
+
* buildAnchorText MUST stay identical to the frontend's version AND the
|
|
9
|
+
* backend's own copy (src/backend/routes/examNotes.ts) — all three derive the
|
|
10
|
+
* anchor strings embedded in / expected from the markdown, and the backend
|
|
11
|
+
* throws mid-transaction (rolled back) on any mismatch. If the frontend's
|
|
12
|
+
* template changes, update this file and confirm the backend's copy still
|
|
13
|
+
* agrees.
|
|
14
|
+
*/
|
|
15
|
+
import type { ExamData } from './types.js';
|
|
16
|
+
export declare function buildAnchorText(questionId: string, blankIndex?: number): string;
|
|
17
|
+
/**
|
|
18
|
+
* Build the markdown representation of an exam for storage as a note, plus
|
|
19
|
+
* the anchor list the backend needs to pre-create one text_note marker per
|
|
20
|
+
* question. Mirrors the frontend's buildExamMarkdown exactly (no
|
|
21
|
+
* referenceImageDataUri support here — that's an AI-generated-source feature
|
|
22
|
+
* not needed for hand-authored exams created via create_exam_note).
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildExamMarkdown(examData: ExamData): {
|
|
25
|
+
markdown: string;
|
|
26
|
+
anchors: Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
anchorText: string;
|
|
29
|
+
blankIndex?: number;
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=examNoteTemplate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examNoteTemplate.d.ts","sourceRoot":"","sources":["../../../src/tools/exam/examNoteTemplate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EACV,QAAQ,EAUT,MAAM,YAAY,CAAC;AAKpB,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAK/E;AAsFD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,GACjB;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzE,CA0BA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const CHOICE_LABELS = ['A', 'B', 'C', 'D', 'E', 'F'];
|
|
2
|
+
const ROMAN = ['I', 'II', 'III', 'IV', 'V'];
|
|
3
|
+
export function buildAnchorText(questionId, blankIndex) {
|
|
4
|
+
if (typeof blankIndex === 'number' && blankIndex > 0) {
|
|
5
|
+
return `Answer ${questionId}.${blankIndex}:`;
|
|
6
|
+
}
|
|
7
|
+
return `Answer ${questionId}:`;
|
|
8
|
+
}
|
|
9
|
+
function renderQuestion(q) {
|
|
10
|
+
switch (q.type) {
|
|
11
|
+
case 'translation':
|
|
12
|
+
return renderTranslation(q);
|
|
13
|
+
case 'sentence-completion':
|
|
14
|
+
return renderSentenceCompletion(q);
|
|
15
|
+
case 'vocab-in-context':
|
|
16
|
+
return renderVocabInContext(q);
|
|
17
|
+
case 'multiple-choice':
|
|
18
|
+
return renderMultipleChoice(q);
|
|
19
|
+
case 'calculation':
|
|
20
|
+
return renderCalculation(q);
|
|
21
|
+
case 'short-answer':
|
|
22
|
+
return renderShortAnswer(q);
|
|
23
|
+
case 'fill-in-the-blank':
|
|
24
|
+
return renderFillInBlank(q);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function renderTranslation(q) {
|
|
28
|
+
return `**${q.questionNum}.** ${q.zhPrompt}\n\n> **${buildAnchorText(q.id)}** _______________________`;
|
|
29
|
+
}
|
|
30
|
+
function renderSentenceCompletion(q) {
|
|
31
|
+
const choices = q.choices
|
|
32
|
+
.map((c, i) => `- (${CHOICE_LABELS[i]}) ${c}`)
|
|
33
|
+
.join('\n');
|
|
34
|
+
return `**${q.questionNum}.** ${q.sentenceWithBlank}\n\n${choices}\n\n> **${buildAnchorText(q.id)}** _ (A/B/C/D)`;
|
|
35
|
+
}
|
|
36
|
+
function renderVocabInContext(q) {
|
|
37
|
+
const sentence = q.sentence.replace(new RegExp(`\\b${q.underlinedWord.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i'), (match) => `<u>${match}</u>`);
|
|
38
|
+
const choices = q.choices
|
|
39
|
+
.map((c, i) => `- (${CHOICE_LABELS[i]}) ${c}`)
|
|
40
|
+
.join('\n');
|
|
41
|
+
return `**${q.questionNum}.** ${sentence}\n\n*The underlined word is closest in meaning to:*\n\n${choices}\n\n> **${buildAnchorText(q.id)}** _ (A/B/C/D)`;
|
|
42
|
+
}
|
|
43
|
+
function renderMultipleChoice(q) {
|
|
44
|
+
const choices = q.choices
|
|
45
|
+
.map((c, i) => `- (${CHOICE_LABELS[i]}) ${c}`)
|
|
46
|
+
.join('\n');
|
|
47
|
+
const letterHint = q.choices
|
|
48
|
+
.map((_, i) => CHOICE_LABELS[i])
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.join('/');
|
|
51
|
+
return `**${q.questionNum}.** ${q.prompt}\n\n${choices}\n\n> **${buildAnchorText(q.id)}** _ (${letterHint})`;
|
|
52
|
+
}
|
|
53
|
+
function renderCalculation(q) {
|
|
54
|
+
const unitHint = q.unit ? ` ${q.unit}` : '';
|
|
55
|
+
return `**${q.questionNum}.** ${q.prompt}\n\n> **${buildAnchorText(q.id)}** _______________________${unitHint}`;
|
|
56
|
+
}
|
|
57
|
+
function renderShortAnswer(q) {
|
|
58
|
+
return `**${q.questionNum}.** ${q.prompt}\n\n> **${buildAnchorText(q.id)}** _______________________`;
|
|
59
|
+
}
|
|
60
|
+
function renderFillInBlank(q) {
|
|
61
|
+
const blankCount = countBlanks(q.prompt);
|
|
62
|
+
if (blankCount <= 1) {
|
|
63
|
+
return `**${q.questionNum}.** ${q.prompt}\n\n> **${buildAnchorText(q.id)}** _______________________`;
|
|
64
|
+
}
|
|
65
|
+
const answerLines = Array.from({ length: blankCount }, (_, i) => {
|
|
66
|
+
const oneBased = i + 1;
|
|
67
|
+
return `> **${buildAnchorText(q.id, oneBased)}** _______________________`;
|
|
68
|
+
}).join('\n');
|
|
69
|
+
return `**${q.questionNum}.** ${q.prompt}\n\n${answerLines}`;
|
|
70
|
+
}
|
|
71
|
+
function countBlanks(prompt) {
|
|
72
|
+
return (prompt.match(/_{3,}/g) ?? []).length;
|
|
73
|
+
}
|
|
74
|
+
function renderSection(section, sectionNum) {
|
|
75
|
+
const numeral = ROMAN[sectionNum - 1] || String(sectionNum);
|
|
76
|
+
const pointsLabel = `${section.points} point${section.points !== 1 ? 's' : ''}`;
|
|
77
|
+
const body = section.questions.map(renderQuestion).join('\n\n');
|
|
78
|
+
return `## ${numeral}. ${section.title} (${pointsLabel})\n\n*${section.instructions}*\n\n${body}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Build the markdown representation of an exam for storage as a note, plus
|
|
82
|
+
* the anchor list the backend needs to pre-create one text_note marker per
|
|
83
|
+
* question. Mirrors the frontend's buildExamMarkdown exactly (no
|
|
84
|
+
* referenceImageDataUri support here — that's an AI-generated-source feature
|
|
85
|
+
* not needed for hand-authored exams created via create_exam_note).
|
|
86
|
+
*/
|
|
87
|
+
export function buildExamMarkdown(examData) {
|
|
88
|
+
const header = `# ${examData.title}\n\n*${examData.date} — ${examData.totalPoints} points total*\n\n**Name:** _________________________ **Score:** _______ / ${examData.totalPoints}`;
|
|
89
|
+
const sectionsMd = examData.sections
|
|
90
|
+
.map((section, i) => renderSection(section, i + 1))
|
|
91
|
+
.join('\n\n---\n\n');
|
|
92
|
+
const markdown = `${header}\n\n---\n\n${sectionsMd}\n`;
|
|
93
|
+
const anchors = [];
|
|
94
|
+
for (const section of examData.sections) {
|
|
95
|
+
for (const q of section.questions) {
|
|
96
|
+
if (q.type === 'fill-in-the-blank') {
|
|
97
|
+
const blanks = countBlanks(q.prompt);
|
|
98
|
+
if (blanks > 1) {
|
|
99
|
+
for (let i = 1; i <= blanks; i++) {
|
|
100
|
+
anchors.push({ id: q.id, anchorText: buildAnchorText(q.id, i), blankIndex: i });
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
anchors.push({ id: q.id, anchorText: buildAnchorText(q.id) });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { markdown, anchors };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=examNoteTemplate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examNoteTemplate.js","sourceRoot":"","sources":["../../../src/tools/exam/examNoteTemplate.ts"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -61,5 +61,45 @@ export declare function syncSpecificFiles(filePaths: string[], dryRun: boolean,
|
|
|
61
61
|
}>;
|
|
62
62
|
isError?: boolean;
|
|
63
63
|
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Split leading YAML frontmatter from a markdown document.
|
|
66
|
+
*
|
|
67
|
+
* The opening `---` must be the very first line and the closing `---` must be on its
|
|
68
|
+
* own line (line-anchored). This deliberately does NOT use `indexOf('---', 3)`: a bare
|
|
69
|
+
* substring search matches a `---` inside a frontmatter value, a `---`/`----` thematic
|
|
70
|
+
* break in the body, or a `---` inside a code fence — which previously caused notes to
|
|
71
|
+
* be truncated / their frontmatter duplicated on sync.
|
|
72
|
+
*
|
|
73
|
+
* @returns raw = whole matched block incl. fences + trailing newline; inner = the YAML
|
|
74
|
+
* between the fences; body = everything after the block. If there is no valid
|
|
75
|
+
* leading frontmatter, raw/inner are '' and body is the full content.
|
|
76
|
+
*/
|
|
77
|
+
export declare function splitFrontmatter(content: string): {
|
|
78
|
+
raw: string;
|
|
79
|
+
inner: string;
|
|
80
|
+
body: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Update frontmatter in file content with new metadata values
|
|
84
|
+
* Preserves existing frontmatter structure and only updates specified fields
|
|
85
|
+
*/
|
|
86
|
+
export declare function updateFrontmatter(content: string, updates: {
|
|
87
|
+
title?: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
keywords?: string[];
|
|
90
|
+
}): string;
|
|
91
|
+
/**
|
|
92
|
+
* Parse markdown content into structure: frontmatter, H1 heading, and body
|
|
93
|
+
*/
|
|
94
|
+
export declare function parseMarkdownStructure(content: string): {
|
|
95
|
+
frontmatter: string;
|
|
96
|
+
h1: string | null;
|
|
97
|
+
body: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Merge local content with cloud content
|
|
101
|
+
* Strategy: Cloud's H1 wins (Noesis edits), Local's body wins (local edits)
|
|
102
|
+
*/
|
|
103
|
+
export declare function mergeContent(localContent: string, cloudContent: string): string;
|
|
64
104
|
export {};
|
|
65
105
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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;
|
|
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"}
|