Search СДАМ ГИА Problems by Query
sdamgia_search_problemsSearch for exam problems in the СДАМ ГИА database by subject and keyword. Returns matching problem IDs for further retrieval.
Instructions
Searches for problems in the СДАМ ГИА database using a text-based query.
When to use:
You want to find problems related to a specific topic (e.g., "quadratic equations", "Newton's laws")
You're exploring available problems in a subject area
You need to discover problem IDs before fetching full details
You want to browse problems by keywords or concepts
Parameters:
subject(required): Subject code to search within (e.g., 'math', 'phys', 'inf')query(required): Search text - minimum 3 characters, maximum 500 characters. Use descriptive terms like "triangle area", "oxidation reactions", "grammar rules"limit(optional): Maximum number of results (1-50, default: 20)response_format(optional): 'markdown' (default) or 'json'
Returns: A list of matching problems with:
problem_ids: Array of problem IDs matching the search query
total: Count of results returned
In markdown format: numbered list with clickable links to each problem
Search behavior:
Performs text-based matching against problem descriptions and metadata
Results are ranked by relevance to your query
Search is optimized for subject-specific terminology
Broad search that returns problem IDs only (not full problem details)
Response format:
Markdown: Formatted list with problem IDs and subject context
JSON: Object with problem_ids array and total count
Example usage:
{
"subject": "math",
"query": "derivative of trigonometric functions",
"limit": 10,
"response_format": "markdown"
}Follow-up workflow:
Use this tool to find relevant problem IDs
Use
sdamgia_get_problemorsdamgia_batch_get_problemsto fetch full details
Notes:
Query must be at least 3 characters for meaningful results
Maximum 50 results per search (use limit parameter)
Search returns IDs only - follow up with get_problem for details
For exact text matching with problem conditions, use
sdamgia_search_by_textinsteadSubject-specific terminology works best for quality results
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| subject | Yes | Subject code to search in | |
| query | Yes | Search query text | |
| limit | No | Maximum number of results to return | |
| response_format | No | markdown |
Implementation Reference
- src/tools/problem-tools.ts:164-183 (handler)The async handler function that executes the sdamgia_search_problems tool logic. It calls client.searchProblems(), maps results, formats the output via formatResponse/formatSearchResultsMarkdown, and returns content.
async ({ subject, query, limit, response_format }) => { try { const problemIds = await client.searchProblems(subject, query, limit); const results = problemIds.map(id => ({ id })); const output = formatResponse( { problem_ids: problemIds, total: problemIds.length }, response_format, () => formatSearchResultsMarkdown(query, results, subject) ); return { content: [{ type: "text", text: output }], structuredContent: { problem_ids: problemIds, total: problemIds.length } }; } catch (error) { throw new Error(`Search failed: ${error}`); } } ); - src/schemas/input-schemas.ts:87-92 (schema)Zod schema SearchProblemsInputSchema defining input validation: subject (enum), query (3-500 chars), limit (1-50, default 20), response_format (markdown/json default markdown).
export const SearchProblemsInputSchema = z.object({ subject: SubjectSchema.describe("Subject code to search in"), query: SearchQuerySchema, limit: LimitSchema, response_format: ResponseFormatSchema }).strict(); - src/tools/problem-tools.ts:100-183 (registration)Registration of the tool 'sdamgia_search_problems' via server.registerTool(), including title, description, inputSchema reference, and annotations (readOnlyHint, idempotentHint).
/** * Search problems by query */ server.registerTool( "sdamgia_search_problems", { title: "Search СДАМ ГИА Problems by Query", description: `**Searches for problems in the СДАМ ГИА database using a text-based query.** **When to use:** - You want to find problems related to a specific topic (e.g., "quadratic equations", "Newton's laws") - You're exploring available problems in a subject area - You need to discover problem IDs before fetching full details - You want to browse problems by keywords or concepts **Parameters:** - \`subject\` (required): Subject code to search within (e.g., 'math', 'phys', 'inf') - \`query\` (required): Search text - minimum 3 characters, maximum 500 characters. Use descriptive terms like "triangle area", "oxidation reactions", "grammar rules" - \`limit\` (optional): Maximum number of results (1-50, default: 20) - \`response_format\` (optional): 'markdown' (default) or 'json' **Returns:** A list of matching problems with: - **problem_ids**: Array of problem IDs matching the search query - **total**: Count of results returned - In markdown format: numbered list with clickable links to each problem **Search behavior:** - Performs text-based matching against problem descriptions and metadata - Results are ranked by relevance to your query - Search is optimized for subject-specific terminology - Broad search that returns problem IDs only (not full problem details) **Response format:** - **Markdown**: Formatted list with problem IDs and subject context - **JSON**: Object with problem_ids array and total count **Example usage:** \`\`\`json { "subject": "math", "query": "derivative of trigonometric functions", "limit": 10, "response_format": "markdown" } \`\`\` **Follow-up workflow:** 1. Use this tool to find relevant problem IDs 2. Use \`sdamgia_get_problem\` or \`sdamgia_batch_get_problems\` to fetch full details **Notes:** - Query must be at least 3 characters for meaningful results - Maximum 50 results per search (use limit parameter) - Search returns IDs only - follow up with get_problem for details - For exact text matching with problem conditions, use \`sdamgia_search_by_text\` instead - Subject-specific terminology works best for quality results`, inputSchema: SearchProblemsInputSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true } }, async ({ subject, query, limit, response_format }) => { try { const problemIds = await client.searchProblems(subject, query, limit); const results = problemIds.map(id => ({ id })); const output = formatResponse( { problem_ids: problemIds, total: problemIds.length }, response_format, () => formatSearchResultsMarkdown(query, results, subject) ); return { content: [{ type: "text", text: output }], structuredContent: { problem_ids: problemIds, total: problemIds.length } }; } catch (error) { throw new Error(`Search failed: ${error}`); } } ); - The client.searchProblems() helper method that performs the HTTP GET to the search endpoint, extracts problem IDs by parsing HTML with cheerio, and returns up to the specified limit.
async searchProblems(subject: Subject, query: string, limit: number = 20): Promise<string[]> { const baseUrl = this.getBaseUrl(subject); const url = `${baseUrl}/search`; try { const response = await this.axiosInstance.get(url, { params: { search: query } }); const $ = cheerio.load(response.data); // Extract problem IDs from search results const problemIds: string[] = []; $(".prob_nums a").each((_, el) => { const href = $(el).attr("href"); const idMatch = href?.match(/id=(\d+)/); if (idMatch) { problemIds.push(idMatch[1]); } }); return problemIds.slice(0, limit); } catch (error) { throw new Error(`Search failed: ${error}`); } } - src/services/formatters.ts:82-138 (helper)Helper function formatSearchResultsMarkdown() that formats search results into a human-readable markdown string with query, subject, total count, and numbered list of problem IDs (with similarity scores if applicable).
export function formatSearchResultsMarkdown( query: string, results: Array<{ id?: string; score?: number; problem_id?: string; similarity?: number; condition_start?: string; condition_end?: string; answer?: string }>, subject: string ): string { let output = `# Search Results\n\n`; output += `**Query**: ${query}\n`; output += `**Subject**: ${subject}\n`; output += `**Total Results**: ${results.length}\n\n`; if (results.length === 0) { output += `No problems found matching the query.\n`; return output; } output += `## Problem IDs\n\n`; results.forEach((result, index) => { // Handle both old format (id, score) and new format (problem_id, similarity, condition_start, etc.) const id = result.problem_id || result.id || ''; const score = result.similarity !== undefined ? result.similarity : result.score; output += `${index + 1}. Problem ${id}`; if (score !== undefined) { output += ` (similarity: ${(score * 100).toFixed(1)}%)`; } output += `\n`; // Add condition preview if available if (result.condition_start && result.condition_start.length > 0) { output += ` **Start**: ${result.condition_start}...\n`; } if (result.condition_end && result.condition_end.length > 0) { output += ` **End**: ...${result.condition_end}\n`; } if (result.answer && result.answer.length > 0) { output += ` **Answer**: ${result.answer}\n`; } output += `\n`; }); return output; } /** * Format batch problems as markdown */ export function formatBatchProblemsMarkdown(problems: Problem[]): string { let output = `# Batch Problems\n\n`; output += `**Total**: ${problems.length}\n\n`; output += `---\n\n`; problems.forEach((problem, index) => { output += formatProblemMarkdown(problem); if (index < problems.length - 1) { output += `---\n\n`; } });