get_education_data
Query Urban Institute's Education Data API to access detailed information on schools, districts, and universities. Specify level, source, topic, and optional filters to retrieve specific education-related data.
Instructions
Retrieve education data from the Urban Institute's Education Data API
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| add_labels | No | Add variable labels when applicable (default: false) | |
| filters | No | Optional query filters (e.g., {year: 2008, grade: [9,10,11,12]}) | |
| level | Yes | API data level to query (e.g., 'schools', 'school-districts', 'college-university') | |
| limit | No | Limit the number of results (default: 100) | |
| source | Yes | API data source to query (e.g., 'ccd', 'ipeds', 'crdc') | |
| subtopic | No | Optional list of grouping parameters (e.g., ['race', 'sex']) | |
| topic | Yes | API data topic to query (e.g., 'enrollment', 'directory') |
Implementation Reference
- src/index.ts:292-378 (handler)Main execution logic for the get_education_data tool. Validates input parameters, builds the API URL using level/source/topic/subtopic, appends query parameters for filters/limit/labels/mode=R, fetches data via axios from Education Data API, returns JSON results as text content, and handles API errors appropriately.case "get_education_data": { const { level, source, topic, subtopic, filters, add_labels, limit = 100 } = request.params.arguments || {}; if (!level || !source || !topic) { throw new McpError( ErrorCode.InvalidParams, "Missing required parameters: level, source, and topic are required" ); } try { // Construct the API URL let url = `${API_BASE_URL}/${level}/${source}/${topic}`; // Add subtopics if provided if (subtopic && Array.isArray(subtopic) && subtopic.length > 0) { url += `/${subtopic.join("/")}`; } // Add query parameters const queryParams = new URLSearchParams(); queryParams.append("limit", String(limit)); if (add_labels) { queryParams.append("add_labels", "true"); } // Add filters if (filters && typeof filters === "object") { Object.entries(filters).forEach(([key, value]) => { if (Array.isArray(value)) { queryParams.append(key, value.join(",")); } else { queryParams.append(key, String(value)); } }); } // Add mode=R to match the R package behavior queryParams.append("mode", "R"); // Make the API request const response = await axios.get(`${url}?${queryParams.toString()}`); // Return the results return { content: [ { type: "text", text: JSON.stringify(response.data.results || response.data, null, 2) } ] }; } catch (error) { if (axios.isAxiosError(error)) { const statusCode = error.response?.status; const message = error.response?.data?.message || error.message; if (statusCode === 404) { throw new McpError( ErrorCode.InvalidRequest, `Endpoint not found: ${level}/${source}/${topic}` ); } else if (statusCode === 400) { throw new McpError( ErrorCode.InvalidParams, `API error: ${message}` ); } else if (statusCode === 413) { throw new McpError( ErrorCode.InvalidParams, "Your requested query returned too many records. Consider limiting the scope of your query." ); } throw new McpError( ErrorCode.InternalError, `API error (${statusCode}): ${message}` ); } throw new McpError( ErrorCode.InternalError, `Error: ${error instanceof Error ? error.message : String(error)}` ); } }
- src/index.ts:197-237 (registration)Tool registration in the ListToolsRequestSchema handler, defining name, description, and input schema for get_education_data.{ name: "get_education_data", description: "Retrieve education data from the Urban Institute's Education Data API", inputSchema: { type: "object", properties: { level: { type: "string", description: "API data level to query (e.g., 'schools', 'school-districts', 'college-university')" }, source: { type: "string", description: "API data source to query (e.g., 'ccd', 'ipeds', 'crdc')" }, topic: { type: "string", description: "API data topic to query (e.g., 'enrollment', 'directory')" }, subtopic: { type: "array", items: { type: "string" }, description: "Optional list of grouping parameters (e.g., ['race', 'sex'])" }, filters: { type: "object", description: "Optional query filters (e.g., {year: 2008, grade: [9,10,11,12]})" }, add_labels: { type: "boolean", description: "Add variable labels when applicable (default: false)" }, limit: { type: "number", description: "Limit the number of results (default: 100)" } }, required: ["level", "source", "topic"] } },
- src/index.ts:200-236 (schema)Input schema definition for the get_education_data tool, specifying properties like level, source, topic (required), subtopic, filters, add_labels, limit.inputSchema: { type: "object", properties: { level: { type: "string", description: "API data level to query (e.g., 'schools', 'school-districts', 'college-university')" }, source: { type: "string", description: "API data source to query (e.g., 'ccd', 'ipeds', 'crdc')" }, topic: { type: "string", description: "API data topic to query (e.g., 'enrollment', 'directory')" }, subtopic: { type: "array", items: { type: "string" }, description: "Optional list of grouping parameters (e.g., ['race', 'sex'])" }, filters: { type: "object", description: "Optional query filters (e.g., {year: 2008, grade: [9,10,11,12]})" }, add_labels: { type: "boolean", description: "Add variable labels when applicable (default: false)" }, limit: { type: "number", description: "Limit the number of results (default: 100)" } }, required: ["level", "source", "topic"] }