get_education_data
Retrieve structured education data from the Urban Institute's API for schools, districts, and universities by specifying level, source, and topic parameters.
Instructions
Retrieve education data from the Urban Institute's Education Data API
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| level | Yes | API data level to query (e.g., 'schools', 'school-districts', 'college-university') | |
| source | Yes | API data source to query (e.g., 'ccd', 'ipeds', 'crdc') | |
| topic | Yes | API data topic to query (e.g., 'enrollment', 'directory') | |
| subtopic | No | Optional list of grouping parameters (e.g., ['race', 'sex']) | |
| filters | No | Optional query filters (e.g., {year: 2008, grade: [9,10,11,12]}) | |
| add_labels | No | Add variable labels when applicable (default: false) | |
| limit | No | Limit the number of results (default: 100) |
Implementation Reference
- src/index.ts:292-378 (handler)The handler for the 'get_education_data' tool. It extracts parameters from the request, validates required fields (level, source, topic), constructs the API URL from https://educationdata.urban.org/api/v1 with subtopics, filters, limits, and labels, makes an axios GET request with mode=R, returns the JSON data as text content, and handles API errors like 404, 400, 413.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:200-236 (schema)Input schema for the get_education_data tool, defining properties like level, source, topic (required), subtopic, filters, add_labels, limit with types and descriptions.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:197-237 (registration)Registration of the get_education_data tool in the ListToolsRequestSchema handler, including name, description, and input schema.{ 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"] } },