235 lines
7.6 KiB
TypeScript
235 lines
7.6 KiB
TypeScript
/**
|
||
* Math teaching resource tools
|
||
*/
|
||
|
||
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
||
import { mcpServer } from '../../server.js';
|
||
import { database, MathResource } from '../../storage/database.js';
|
||
import { randomUUID } from 'crypto';
|
||
|
||
export function registerMathTools(): void {
|
||
// Search math resources
|
||
mcpServer.registerTool(
|
||
{
|
||
name: 'math_resource_search',
|
||
description: 'Search for math teaching resources (worksheets, problems, tools)',
|
||
inputSchema: {
|
||
type: 'object',
|
||
properties: {
|
||
query: {
|
||
type: 'string',
|
||
description: 'Search query',
|
||
},
|
||
grade: {
|
||
type: 'string',
|
||
description: 'Grade level (e.g., "1st", "2nd", "elementary", "middle", "high")',
|
||
},
|
||
},
|
||
required: ['query'],
|
||
},
|
||
},
|
||
async (args) => {
|
||
const query = args.query as string;
|
||
const grade = args.grade as string | undefined;
|
||
|
||
const resources = database.searchMathResources(query, grade);
|
||
|
||
if (resources.length === 0) {
|
||
return {
|
||
content: [
|
||
{
|
||
type: 'text',
|
||
text: `No math resources found matching "${query}"${grade ? ` for grade ${grade}` : ''}.\n\nYou can save resources using math_resource_save tool.`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
|
||
const results = resources
|
||
.map(
|
||
(r) =>
|
||
`Title: ${r.title}\nGrade: ${r.grade || 'N/A'}\nDifficulty: ${r.difficulty || 'N/A'}\nTags: ${r.tags.join(', ')}\n\nContent:\n${r.content}\n---`
|
||
)
|
||
.join('\n\n');
|
||
|
||
return {
|
||
content: [
|
||
{
|
||
type: 'text',
|
||
text: `Found ${resources.length} math resource(s):\n\n${results}`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
);
|
||
|
||
// Generate math problems
|
||
mcpServer.registerTool(
|
||
{
|
||
name: 'math_problem_generate',
|
||
description: 'Generate math problems by grade and difficulty',
|
||
inputSchema: {
|
||
type: 'object',
|
||
properties: {
|
||
grade: {
|
||
type: 'string',
|
||
description: 'Grade level (e.g., "1st", "2nd", "elementary", "middle", "high")',
|
||
},
|
||
difficulty: {
|
||
type: 'string',
|
||
description: 'Difficulty level (easy, medium, hard)',
|
||
default: 'medium',
|
||
},
|
||
topic: {
|
||
type: 'string',
|
||
description: 'Math topic (e.g., "addition", "multiplication", "algebra", "geometry")',
|
||
},
|
||
count: {
|
||
type: 'number',
|
||
description: 'Number of problems to generate',
|
||
default: 5,
|
||
},
|
||
},
|
||
required: ['grade'],
|
||
},
|
||
},
|
||
async (args) => {
|
||
const grade = args.grade as string;
|
||
const difficulty = (args.difficulty as string) || 'medium';
|
||
const topic = args.topic as string | undefined;
|
||
const count = (args.count as number) || 5;
|
||
|
||
// Generate problems based on grade and difficulty
|
||
const problems: string[] = [];
|
||
|
||
if (grade.includes('1st') || grade.includes('2nd') || grade === 'elementary') {
|
||
// Elementary level
|
||
for (let i = 0; i < count; i++) {
|
||
if (topic === 'addition' || !topic) {
|
||
const a = Math.floor(Math.random() * 20) + 1;
|
||
const b = Math.floor(Math.random() * 20) + 1;
|
||
problems.push(`${a} + ${b} = ?`);
|
||
} else if (topic === 'subtraction') {
|
||
const a = Math.floor(Math.random() * 20) + 10;
|
||
const b = Math.floor(Math.random() * a) + 1;
|
||
problems.push(`${a} - ${b} = ?`);
|
||
} else if (topic === 'multiplication') {
|
||
const a = Math.floor(Math.random() * 10) + 1;
|
||
const b = Math.floor(Math.random() * 10) + 1;
|
||
problems.push(`${a} × ${b} = ?`);
|
||
}
|
||
}
|
||
} else if (grade.includes('middle') || grade.includes('6th') || grade.includes('7th') || grade.includes('8th')) {
|
||
// Middle school level
|
||
for (let i = 0; i < count; i++) {
|
||
if (topic === 'algebra' || !topic) {
|
||
const a = Math.floor(Math.random() * 10) + 1;
|
||
const b = Math.floor(Math.random() * 20) - 10;
|
||
const c = Math.floor(Math.random() * 20) - 10;
|
||
problems.push(`Solve for x: ${a}x + ${b} = ${c}`);
|
||
} else if (topic === 'fractions') {
|
||
const num1 = Math.floor(Math.random() * 10) + 1;
|
||
const den1 = Math.floor(Math.random() * 10) + 1;
|
||
const num2 = Math.floor(Math.random() * 10) + 1;
|
||
const den2 = Math.floor(Math.random() * 10) + 1;
|
||
problems.push(`Add: ${num1}/${den1} + ${num2}/${den2} = ?`);
|
||
} else if (topic === 'geometry') {
|
||
const side = Math.floor(Math.random() * 10) + 1;
|
||
problems.push(`Find the area of a square with side length ${side}`);
|
||
}
|
||
}
|
||
} else {
|
||
// High school level
|
||
for (let i = 0; i < count; i++) {
|
||
if (topic === 'algebra' || !topic) {
|
||
const a = Math.floor(Math.random() * 5) + 1;
|
||
const b = Math.floor(Math.random() * 10) - 5;
|
||
const c = Math.floor(Math.random() * 10) - 5;
|
||
problems.push(`Solve: ${a}x² + ${b}x + ${c} = 0`);
|
||
} else if (topic === 'geometry') {
|
||
const r = Math.floor(Math.random() * 10) + 1;
|
||
problems.push(`Find the area of a circle with radius ${r} (use π = 3.14)`);
|
||
} else if (topic === 'trigonometry') {
|
||
const angle = [30, 45, 60][Math.floor(Math.random() * 3)];
|
||
problems.push(`Find sin(${angle}°)`);
|
||
}
|
||
}
|
||
}
|
||
|
||
const problemsText = problems.map((p, i) => `${i + 1}. ${p}`).join('\n');
|
||
|
||
return {
|
||
content: [
|
||
{
|
||
type: 'text',
|
||
text: `Generated ${count} math problem(s) for ${grade} grade (${difficulty} difficulty)${topic ? ` - Topic: ${topic}` : ''}:\n\n${problemsText}`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
);
|
||
|
||
// Save math resource
|
||
mcpServer.registerTool(
|
||
{
|
||
name: 'math_resource_save',
|
||
description: 'Save a math teaching resource',
|
||
inputSchema: {
|
||
type: 'object',
|
||
properties: {
|
||
title: {
|
||
type: 'string',
|
||
description: 'Title of the resource',
|
||
},
|
||
content: {
|
||
type: 'string',
|
||
description: 'Content of the resource (worksheet, problem set, etc.)',
|
||
},
|
||
grade: {
|
||
type: 'string',
|
||
description: 'Grade level',
|
||
},
|
||
difficulty: {
|
||
type: 'string',
|
||
description: 'Difficulty level',
|
||
},
|
||
tags: {
|
||
type: 'array',
|
||
items: { type: 'string' },
|
||
description: 'Tags for categorization',
|
||
},
|
||
id: {
|
||
type: 'string',
|
||
description: 'Optional ID for updating existing resource',
|
||
},
|
||
},
|
||
required: ['title', 'content'],
|
||
},
|
||
},
|
||
async (args) => {
|
||
const now = new Date().toISOString();
|
||
const resource: MathResource = {
|
||
id: (args.id as string) || randomUUID(),
|
||
title: args.title as string,
|
||
content: args.content as string,
|
||
grade: args.grade as string | undefined,
|
||
difficulty: args.difficulty as string | undefined,
|
||
tags: (args.tags as string[]) || [],
|
||
createdAt: now,
|
||
};
|
||
|
||
database.saveMathResource(resource);
|
||
|
||
return {
|
||
content: [
|
||
{
|
||
type: 'text',
|
||
text: `Math resource "${resource.title}" saved successfully with ID: ${resource.id}`,
|
||
},
|
||
],
|
||
};
|
||
}
|
||
);
|
||
}
|
||
|