follow_up
Explore concepts, code examples, handouts, or reference projects after submitting answers to enhance learning and understanding.
Instructions
Handle post-answer follow-up actions. Use after submit_answer to explore concepts, code examples, handouts, or reference projects.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| questionId | Yes | The question ID from the previous answer | |
| action | Yes | The follow-up action to take |
Implementation Reference
- src/tools/follow-up.ts:34-182 (handler)The registration and handler implementation for the 'follow_up' tool.
export function registerFollowUp(server: McpServer, _db: Database.Database, _userConfig: UserConfig): void { server.tool( 'follow_up', 'Handle post-answer follow-up actions. Use after submit_answer to explore concepts, code examples, handouts, or reference projects.', { questionId: z.string().describe('The question ID from the previous answer'), action: z.enum(FOLLOW_UP_ACTIONS).describe('The follow-up action to take'), }, async ({ questionId, action }) => { const question = findQuestion(questionId); if (!question) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'Question not found', questionId }) }], isError: true, }; } switch (action) { case 'next': { return { content: [{ type: 'text' as const, text: JSON.stringify({ instruction: 'Call get_practice_question to get the next question.', taskStatement: question.taskStatement, domainId: question.domainId, }, null, 2), }], }; } case 'code_example': { const handout = loadHandout(question.taskStatement); if (!handout) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }], isError: true, }; } const codeExample = extractSection(handout, 'Code Example'); if (!codeExample) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Code Example section found in handout', taskStatement: question.taskStatement }) }], isError: true, }; } return { content: [{ type: 'text' as const, text: JSON.stringify({ taskStatement: question.taskStatement, codeExample, }, null, 2), }], }; } case 'concept': { const handout = loadHandout(question.taskStatement); if (!handout) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }], isError: true, }; } const concept = extractSection(handout, 'Concept'); if (!concept) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No Concept section found in handout', taskStatement: question.taskStatement }) }], isError: true, }; } return { content: [{ type: 'text' as const, text: JSON.stringify({ taskStatement: question.taskStatement, concept, }, null, 2), }], }; } case 'handout': { const handout = loadHandout(question.taskStatement); if (!handout) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No handout found for this task statement', taskStatement: question.taskStatement }) }], isError: true, }; } return { content: [{ type: 'text' as const, text: JSON.stringify({ taskStatement: question.taskStatement, handout, }, null, 2), }], }; } case 'project': { const projectId = DOMAIN_PROJECT_MAP[question.domainId] ?? null; if (!projectId) { return { content: [{ type: 'text' as const, text: JSON.stringify({ error: 'No reference project mapped for this domain', domainId: question.domainId }) }], isError: true, }; } return { content: [{ type: 'text' as const, text: JSON.stringify({ instruction: 'Call scaffold_project to explore the reference project for this domain.', projectId, domainId: question.domainId, }, null, 2), }], }; } case 'why_wrong': { const incorrectOptions = Object.entries(question.whyWrongMap) .filter(([key]) => key !== question.correctAnswer) .reduce<Record<string, string>>((acc, [key, value]) => { if (value) { return { ...acc, [key]: value }; } return acc; }, {}); return { content: [{ type: 'text' as const, text: JSON.stringify({ questionId: question.id, correctAnswer: question.correctAnswer, explanation: question.explanation, whyOthersAreWrong: incorrectOptions, }, null, 2), }], }; } } } ); }