college-scorecard-mcp-server
Server Details
Search, compare, and analyze U.S. college data — costs, earnings, programs, and outcomes.
- Status
- Healthy
- Uptime
- 99.8% over 23 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/college-scorecard-mcp-server
- GitHub Stars
- 1
- Server Listing
- College Scorecard MCP Server
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 9 tools
Most tools have clearly distinct scopes: search_schools finds schools, get_school retrieves profiles, compare_schools compares schools, and search_programs vs get_programs separates cross-institution from single-school program queries. There is some conceptual overlap between get_earnings, get_programs earnings, and value_analysis, but the descriptions give enough guidance to choose correctly.
All tools use a consistent scorecard_ prefix and snake_case, and nearly all follow a verb_noun pattern such as get_school, search_programs, lookup_cip, and compare_schools. The main deviation is scorecard_value_analysis, which is a noun phrase rather than a verb-led tool name, but it remains readable and predictable.
Nine tools is well within the appropriate range for a domain as broad as College Scorecard data. The set covers lookup, search, retrieval, comparison, programs, earnings, fields, and value analysis without feeling bloated.
The tool surface covers the main College Scorecard workflows: school discovery, profiles, comparison, field catalog exploration, CIP lookup, program search/retrieval, earnings, and value analysis. Custom field access through get_school plus list_fields also provides an extensibility path for less common data needs.
Available Tools
9 toolsscorecard_compare_schoolsCompare SchoolsARead-onlyInspect
Side-by-side comparison of the first five distinct normalized school IDs, accepting up to 1,000 raw IDs. Remaining IDs are unprocessed; request them separately. Ordinal competition ranks share ties; shared OPEID6 outcomes and mixed-period price rows are unranked. Topics: costs, admissions, outcomes, aid. Use scorecard_get_school for full profiles.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | 2–1,000 raw school IDs; first five distinct normalized IDs compared. | |
| topic | Yes | Comparison topic: costs, admissions, outcomes, or aid. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | No | Comparison rows — one per metric, with per-school values and ranks. |
| error | No | Present when the call failed. Absent on success. |
| topic | No | The comparison topic used. |
| notice | No | Warning if some requested IDs returned no record. |
| schools | No | Schools in the comparison set, in the same order as the ids input. |
| summary | No | Brief interpretive summary highlighting the most notable relative differences. |
| missing_ids | No | Processed IDs without records. |
| unprocessed_ids | No | Distinct normalized IDs beyond the five-school serving cap. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only and open-world annotations, it discloses that only the first five distinct normalized IDs are processed and all remaining IDs are left unprocessed. It also explains non-obvious ranking behavior: ordinal competition ranks share ties, while shared OPEID6 outcomes and mixed-period price rows are unranked.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loads the comparison scope and processing limit before covering ranking caveats and the alternative tool. The topic list duplicates the schema enum, and the ranking sentence is dense, but there is little overall waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a comparison tool with several edge cases, it covers processing limits, leftover-ID handling, ranking exceptions, topic scope, and the full-profile alternative. Combined with the complete input schema, output schema, and annotations, this provides sufficient context to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents accepted ID forms, the 2–1,000 range, first-five behavior, and the topic enum. The description reiterates normalization, truncation, and topics but adds little parameter-specific meaning beyond those structured fields, so the high-coverage baseline applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a side-by-side school comparison, its five-distinct-ID scope, and the available comparison topics. It also distinguishes the tool from scorecard_get_school, which is intended for full profiles.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit alternative and selection condition: use scorecard_get_school for full profiles rather than comparison. It also tells the agent to request IDs beyond the first five separately, providing clear guidance for oversized inputs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_get_earningsGet School EarningsARead-onlyIdempotentInspect
Institution-level earnings of federally aided undergraduate entrants working and not enrolled, regardless of completion. Reports medians at 6/8/10 years after entry, 6/10-year percentiles, and non-male/male 6-year medians. For graduate program earnings use scorecard_get_programs. years selects API data-file start years (1996–2025), including files without earnings observations. Per-metric availability and official cohort/measurement/dollar context accompany values; unknown metadata stays absent. No re-inflation is performed.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | School ID from scorecard_search_schools. | |
| years | No | Optional API data-file start years from 1996–2025 (e.g. [2003, 2011, 2020]); valid files may lack observations. Omit or pass [] for snapshot only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| trend | No | Historical rows by API data-file start year. Present only when nonempty years were supplied. |
| current | No | Most recent available earnings snapshot. |
| ope6_id | No | Provider OPEID6 identifier, preserving leading zeros. |
| school_id | No | School unit ID. |
| suppressed | No | True only when every supported current metric has an explicit privacy marker. |
| school_name | No | Institution name. |
| metric_scope | No | Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific. |
| current_context | No | Official latest provenance keyed by metric, independent of returned values. |
| suppression_note | No | Explains suppression when suppressed=true. |
| current_availability | No | Availability keyed by every supported current earnings metric. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered; the description adds genuine context beyond that. It warns that years can select data files with no earnings observations, that per-metric availability and official cohort/measurement/dollar framing accompany values, that unknown metadata is omitted rather than inferred, and that no re-inflation is applied — all material to interpreting sparse or missing results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content is front-loaded: what is reported, then the sibling alternative, then parameter and data-quality caveats. Sentences are dense but each carries substantive information; the metric enumeration is long yet necessary to describe the output shape, with only minor redundancy between the description and the schema on years.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description still covers cohort definition, metric set, availability caveats, and sibling routing. What remains thin is edge behavior — e.g., failure modes for invalid ids or how sparse results are represented — leaving it strong but not exhaustive for a read tool with dual id formats.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both id and years are already documented in detail, including the 1996–2025 year bounds and the note that valid files may lack observations. The description's statement that years selects 'API data-file start years' largely restates the schema, adding only marginal emphasis on empty-file behavior, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource and scope — institution-level earnings for federally aided undergraduate entrants who are working and not enrolled, regardless of completion — and enumerates exactly what is reported (6/8/10-year medians, 6/10-year percentiles, non-male/male 6-year medians). It also explicitly routes graduate-level earnings to scorecard_get_programs, so an agent can separate it from that sibling without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear routing rule ('For graduate program earnings use scorecard_get_programs') and explains how the optional years array changes behavior, including the caveat that some files lack observations. It stops short of stating broader exclusions, such as when to prefer scorecard_value_analysis or compare tools, but the primary alternative is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_get_programsGet School ProgramsARead-onlyIdempotentInspect
Page through field-of-study programs at one school, ranked and filtered by completion-based one-year earnings. Legacy highest-credential earnings remain separate from current one- and four-year completion series, with dictionary provenance. Earnings and debt pool across campuses sharing OPEID6 within CIP/credential; awards are campus-specific. Use scorecard_lookup_cip to find CIP codes by name.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | School ID from scorecard_search_schools. | |
| limit | No | Program rows per response; values above 100 normalize to 100. | |
| offset | No | Zero-based program row offset after filtering and stable earnings ordering. | |
| cip_code | No | Filter to one 4-digit CIP code, dotted or undotted (e.g. "11.07" or "1107" for Computer Science). Returns one row per credential level the school offers in that program. | |
| min_earnings | No | Minimum completion-based one-year median earnings; no legacy fallback. | |
| credential_level | No | Filter by credential level: 1=undergraduate certificate, 2=associate, 3=bachelor, 4=post-baccalaureate certificate, 5=master, 6=doctoral, 7=first professional, 8=graduate/professional certificate, 99=non-credential. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| limit | No | Effective program row limit, at most 100. |
| query | No | Normalized effective school ID and program selectors. |
| shown | No | Program rows returned on this page. |
| total | No | Total matching programs before row pagination. |
| notice | No | Guidance when no programs match or some earnings are unavailable or privacy-suppressed. |
| offset | No | Effective zero-based program offset. |
| ope6_id | No | Provider OPEID6 group identifier, preserving leading zeros; null when absent. |
| programs | No | One page of matching programs, stably sorted by completion-based one-year earnings descending, with unavailable current earnings last. |
| school_id | No | School unit ID. |
| truncated | No | More matching program rows remain. |
| nextOffset | No | Next program row offset, or null when exhausted. |
| provenance | No | Dictionary cohort, measurement, and dollar provenance for each population. |
| school_name | No | Institution name. |
| metric_scope | No | Metric aggregation scope within CIP and credential. |
| suppressed_count | No | Matching programs with confirmed privacy-suppressed legacy highest-credential earnings, before row paging. |
| unavailable_count | No | Matching programs with unavailable legacy highest-credential earnings of unknown cause, before row paging. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint/idempotentHint annotations, the description discloses important data behavior: legacy highest-credential earnings are separate from current completion series, earnings and debt pool across campuses sharing OPEID6 within CIP/credential, and awards remain campus-specific. These caveats materially affect interpretation of the results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core action and then layers in relevant caveats without filler. It is somewhat dense, especially 'dictionary provenance,' but every sentence contributes useful context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the full input schema, output schema, and annotations, the definition covers the essential data semantics an agent needs for correct interpretation. The main remaining gap is explicit routing against sibling program-search tools, but the core behavior is otherwise well specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters, including CIP format, credential levels, and offset behavior. The description reinforces the completion-based earnings filter and points to CIP lookup, but adds little parameter-level meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Page through field-of-study programs at one school,' with scope 'ranked and filtered by completion-based one-year earnings.' This is clear, but it does not explicitly distinguish this tool from sibling scorecard_search_programs except through the 'one school' constraint.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a useful pointer to scorecard_lookup_cip for finding CIP codes, which clarifies one supporting workflow. However, it does not say when to use this tool versus scorecard_search_programs or scorecard_get_earnings, and it provides no explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_get_schoolGet School ProfileARead-onlyIdempotentInspect
Institutional profiles for one or more school IDs. Accepts up to 1,000 elements, deduplicates normalized IDs, serves the first 100 distinct IDs, and reports missing and unprocessed IDs separately. Use scorecard_compare_schools for comparisons. Custom fields return requested paths and their JSON values in selected_fields, absent paths in absent_fields, and real identity; default profiles include costs, admissions, outcomes, aid, and completion rates.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Positive safe integer school ID or up to 1,000 raw elements. First 100 distinct normalized IDs served; discover IDs with scorecard_search_schools. | |
| fields | No | Optional comma-separated list of custom field paths from scorecard_list_fields. Overrides the default field set. | |
| program_limit | No | Projected program positions per parent array; values above 100 are clamped to 100. | |
| program_offset | No | Zero-based position in each projected program parent array. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Warning when some requested IDs returned no record. |
| schools | No | Full profiles for the requested school(s). |
| truncated | No | True when any projected program parent has remaining positions. |
| missing_ids | No | Processed distinct IDs with no returned record. |
| total_found | No | Number of records returned. |
| total_requested | No | Number of IDs requested. |
| unprocessed_ids | No | Distinct IDs beyond the 100-ID serving cap, in caller order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so safety is covered; the description adds the genuinely important batch semantics — 1,000 accepted, deduplication of normalized IDs, only the first 100 distinct IDs served, and missing versus unprocessed reported separately. The phrase 'real identity' is unexplained jargon, keeping this short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the resource and the batch limits, then the sibling alternative, then field semantics — a logical ordering with no wasted clauses. It is dense and a few phrases ('real identity') are opaque rather than concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter, read-only lookup with a full schema and an output schema, the description supplies the batching, truncation, and field-override behavior an agent needs to call it correctly. Remaining gaps (pagination of program arrays, return shape) are covered by the structured fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by explaining what the fields parameter produces (requested paths and their JSON values in selected_fields, absent paths in absent_fields) and by enumerating the default field set. It does not cover program_limit clamping, but that is documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific resource and scope ('Institutional profiles for one or more school IDs') and immediately distinguishes itself from the sibling compare tool. An agent can tell what it returns without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes comparisons to scorecard_compare_schools and explains that custom fields require scorecard_list_fields while omitting the argument yields the default profile. It does not restate the schema's guidance about discovering IDs via scorecard_search_schools, but the when-to-use context is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_list_fieldsList Scorecard FieldsARead-onlyIdempotentInspect
Search the College Scorecard field catalog by keyword. Returns matching field paths, descriptions, data types, and whether each field supports API-side sorting. Use before passing custom field paths to the fields parameter on scorecard_get_school to find a supported path. Served entirely from embedded static data — no API call, no rate limit impact.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Requested limit; serving cap 100, hard ceiling 1,000. | |
| query | Yes | Keyword to search the field catalog (e.g. "tuition", "earnings", "admissions", "debt"). Matches against field paths, descriptions, and category names. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The limit that was applied. |
| tip | No | Usage tip for unsortable fields when relevant. |
| error | No | Present when the call failed. Absent on success. |
| query | No | The search query used. |
| shown | No | Number of fields returned. |
| notice | No | No-match guidance. |
| results | No | Matching field entries ranked by relevance. |
| guidance | No | Concrete narrowing guidance when matches remain. |
| truncated | No | True when results were capped at the limit. |
| queryContext | No | Effective selectors. |
| totalMatches | No | Number of matching fields found. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so safety is covered structurally. The description adds genuinely new operational context: it is served from embedded static data with no API call and no rate limit impact, which affects whether an agent should worry about throttling. Minor remaining gap: it doesn't say how results are ranked or truncated when many fields match.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each doing distinct work: what it searches, what it returns, and when/how to use it. The no-API-call caveat is placed last where it belongs as a secondary reassurance rather than burying the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't enumerate return fields, yet it still summarizes them helpfully. Purpose, workflow placement, and cost profile are all covered, leaving nothing an agent needs in order to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both the query keyword semantics and the limit's serving cap vs. hard ceiling are already documented in the schema. The description mentions 'by keyword' but adds no format, matching, or limit guidance beyond what the schema provides — the baseline 3 for full coverage applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — search the College Scorecard field catalog by keyword — and distinguishes itself from data-returning siblings like scorecard_get_school by being a catalog lookup. The follow-on sentence describing returned attributes (field paths, descriptions, data types, sortability) sharpens the scope further.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the downstream use case and the sibling it feeds: 'Use before passing custom field paths to the fields parameter on scorecard_get_school to find a supported path.' The agent gets both a precondition and an ordering relationship, not just an implied purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_lookup_cipLookup CIP CodeARead-onlyIdempotentInspect
Search the Classification of Instructional Programs (CIP) taxonomy by keyword or partial name. Returns matching CIP codes with standard titles. Use this before passing cip_code filters to scorecard_search_programs or scorecard_get_programs when you know a program by name but not its code. Served entirely from embedded static data — no API call, no rate limit impact.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Requested limit; serving cap 50, hard ceiling 1,000. | |
| query | Yes | Search term — program name keyword (e.g. "computer science", "nursing", "business"). Matches against CIP titles and family names. | |
| offset | No | Zero-based offset into the complete relevance-ordered matches. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The limit that was applied. |
| error | No | Present when the call failed. Absent on success. |
| query | No | The search query used. |
| shown | No | Number of CIP codes returned. |
| notice | No | No-match guidance. |
| offset | No | Zero-based offset of this result page. |
| results | No | Matching CIP entries ranked by relevance. |
| guidance | No | Concrete narrowing guidance when matches remain. |
| truncated | No | True when results were capped at the limit. |
| nextOffset | No | Offset to request next; absent when no matches remain. |
| queryContext | No | Effective selectors. |
| totalMatches | No | Number of matches found. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, but the description adds genuinely new operational context: results are served entirely from embedded static data with no API call and no rate-limit impact, which tells an agent it can call this freely. It does not discuss match ordering or how relevance ranking behaves across pages, which would round this out.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying distinct information: what it searches, what it returns, when to use it versus siblings, and its cost profile. The usage guidance is front-loaded after the purpose statement with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full parameter documentation, the description covers purpose, routing, and cost. The only thin area is result-set behavior for broad queries — it doesn't hint that matches may exceed the serving cap and require offset paging, though the schema does note the cap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so query, limit, and offset are each documented in the schema, including the 50-item serving cap versus the 1,000 hard ceiling. The description restates the keyword/partial-name matching behavior that the schema already specifies, adding little beyond it, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource — search the CIP taxonomy by keyword or partial name — and states exactly what comes back (matching CIP codes with standard titles). It is clearly distinguishable from the sibling lookup/search tools because it operates on a code taxonomy, not on institutions or programs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit use case and names the two alternatives it feeds into: 'Use this before passing cip_code filters to scorecard_search_programs or scorecard_get_programs when you know a program by name but not its code.' The condition that selects this tool over those siblings is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_search_programsSearch ProgramsARead-onlyInspect
Find programs across institutions, ranked and filtered by completion-based one-year median earnings within the fetched school page. Legacy highest-credential values remain separate with their own provenance. Earnings and debt pool across campuses sharing OPEID6 within CIP/credential; awards are campus-specific. School page/per_page/total count schools; limit/offset page the matching program rows. Follow next to drain this school page before advancing to the next school page. Use scorecard_lookup_cip to find CIP codes.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Zero-indexed page number. | |
| limit | No | Program rows per response; values above 100 normalize to 100. | |
| state | No | Comma-separated two-letter state codes; case and whitespace normalized, blanks unset. | |
| offset | No | Zero-based row offset within the filtered and sorted school page. | |
| cip_code | No | CIP 4-digit code to search for (e.g. "11.07" for Computer Science). Use scorecard_lookup_cip to find codes. | |
| max_debt | No | Maximum median cumulative Stafford/Grad PLUS debt across institutions at the same academic level, inclusive; excludes unavailable debt. | |
| per_page | No | Schools per page (max 100); program rows may exceed this count. | |
| ownership | No | Restrict to school type: 1=public, 2=private nonprofit, 3=for-profit. | |
| min_earnings | No | Minimum completion-based one-year median earnings, inclusive, without legacy fallback; filters this school page locally while school totals remain unchanged. | |
| program_name | No | Case-insensitive title substring matched within the fetched school page. Ignored when cip_code is provided; use cip_code for upstream program matching. | |
| max_net_price | No | Maximum average net price at the school. | |
| credential_level | No | Provider credential selector: 1=undergraduate certificate, 2=associate, 3=bachelor, 4=post-baccalaureate certificate, 5=master, 6=doctoral, 7=first professional, 8=graduate/professional certificate, 99=non-credential; other integer levels may return no matches. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The effective program row limit that was applied. |
| next | No | Continuation using the same selectors and limits; null when exhausted. |
| page | No | Current page (zero-indexed). |
| error | No | Present when the call failed. Absent on success. |
| limit | No | Effective program row limit, at most 100. |
| query | No | Normalized effective selectors and pagination defaults. |
| shown | No | Program rows returned in this response. |
| total | No | Total schools matching upstream filters, before pagination and local program filtering. |
| notice | No | Recovery hint when no programs match or earnings data is unavailable. |
| offset | No | Effective zero-based row offset within this school page. |
| per_page | No | Results per page used. |
| programs | No | One page of program rows retaining credential identities, stably sorted by completion-based one-year earnings descending, with unavailable current earnings last. |
| truncated | No | True when more program rows or a later school page remain. |
| nextOffset | No | Next row offset on this school page, or null when drained. |
| provenance | No | Dictionary provenance for each distinct program population. |
| totalCount | No | Total schools matching upstream filters, before pagination and local program filtering. |
| metric_scope | No | Aggregation scope within CIP and credential identity. |
| schools_shown | No | Schools returned on this school page. |
| total_programs | No | Matching program rows on the fetched school page before row pagination. |
| suppressed_count | No | Matching programs with confirmed privacy-suppressed legacy highest-credential earnings, before row paging. |
| unavailable_count | No | Matching programs with unavailable legacy highest-credential earnings of unknown cause, before row paging. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint; the description adds substantial non-obvious behavior — earnings/debt pool across campuses sharing OPEID6 while awards are campus-specific, legacy credential values carry separate provenance, and min_earnings filters only the local school page without changing school totals. It stops short of noting rate limits or output shape, but this is well beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded and every sentence carries information, but some phrasing is terse to the point of opacity ('Legacy highest-credential values remain separate with their own provenance') and the pagination-tier sentence is dense. No filler, though it could be ordered more cleanly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter tool with an output schema, the description covers the genuinely hard parts: two-tier pagination, cross-campus pooling, and local filtering semantics. The main remaining gap is sibling disambiguation against scorecard_get_programs and scorecard_search_schools, which an agent would still have to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real meaning the schema does not: it explains that page/per_page/total govern the school tier while limit/offset page the matching program rows within that tier, which is essential to using 12 parameters correctly. The 'without legacy fallback' note on min_earnings also clarifies a subtlety the schema only hints at.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Find programs across institutions, ranked and filtered by completion-based one-year median earnings'), so the agent knows exactly what the tool returns. It does not distinguish itself from the sibling scorecard_get_programs, which is the closest-looking alternative, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides two concrete usage instructions: use scorecard_lookup_cip to resolve CIP codes, and follow 'next' to drain a school page before advancing. However, it never says when to prefer this over scorecard_get_programs or scorecard_search_schools, so the core selection decision is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_search_schoolsSearch SchoolsARead-onlyInspect
Search and filter U.S. colleges and universities by name, location, type, size, and acceptance rate. Returns core identity and cost metrics. Use scorecard_get_school for profiles or scorecard_search_programs for programs. Geographic distance requires a U.S. ZIP; ZIP alone uses the provider default radius. State accepts comma-separated two-letter codes (e.g. WA,CA). Ownership: 1=public, 2=private nonprofit, 3=for-profit. Degree level: 0=Not classified, 1=certificate, 2=associate, 3=bachelor, 4=Entirely graduate-degree granting.
| Name | Required | Description | Default |
|---|---|---|---|
| zip | No | Five-digit U.S. ZIP or ZIP+4. Alone uses the provider default radius; blank is unset. | |
| page | No | Zero-indexed page number for pagination. | |
| sort | No | Upstream sort expression on an indexed field, e.g. "latest.cost.avg_net_price.overall:asc" or ":desc" for reverse order. Use scorecard_list_fields for sort support; omission keeps API ordering. | |
| query | No | School name search — partial or full name; all words must appear. | |
| state | No | Comma-separated two-letter state codes; case and whitespace normalized, blanks unset. | |
| cip_code | No | Filter to schools offering this CIP 4-digit program code (e.g. "11.07"). Use scorecard_lookup_cip to find codes. | |
| distance | No | Nonnegative radius: bare miles, mi, or km, including decimals. Requires meaningful zip. | |
| men_only | No | True selects men-only institutions; false selects institutions explicitly marked not men-only. Omit to include unknown values. | |
| per_page | No | Results per page (max 100). | |
| ownership | No | Control type: 1=public, 2=private nonprofit, 3=private for-profit. | |
| size_range | No | Undergraduate enrollment size range. Omit for no size filter. | |
| women_only | No | True selects women-only institutions; false selects institutions explicitly marked not women-only. Omit to include unknown values. | |
| degree_level | No | Predominant degree: 0=Not classified, 1=certificate, 2=associate, 3=bachelor, 4=Entirely graduate-degree granting. | |
| acceptance_rate_range | No | Acceptance rate range as decimals (0–1). Omit for no filter. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page limit that was applied. |
| page | No | Current page (zero-indexed). |
| error | No | Present when the call failed. Absent on success. |
| query | No | Normalized effective selectors and pagination defaults. |
| shown | No | Institutions returned on this page. |
| total | No | Total institutions matching the filters (before pagination). |
| notice | No | Recovery hint when results are empty — echoes applied filters and suggests how to broaden. |
| schools | No | Matching institutions. |
| per_page | No | Results per page used. |
| truncated | No | True when school pagination metadata indicates a later page exists. |
| totalCount | No | Total institutions matching the filters, before pagination. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds useful behavioral context beyond them: the result scope (core identity and cost metrics) and the silent default-radius behavior when only a ZIP is supplied. It does not discuss pagination limits or empty-result behavior, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then alternatives, then parameter notes, with no filler sentences. It loses a little by restating the ownership and degree-level code tables that the schema already carries verbatim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 14-parameter search tool with nested range objects and an output schema, the description covers purpose, sibling routing, geographic and state syntax, and the coded filters. Return values can be left to the output schema, so nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented, and the numeric code mappings for ownership and degree_level are repeated almost verbatim from the schema. The ZIP/distance interaction is the one place it adds meaning beyond the schema, so this sits at the baseline for a fully-covered schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (search/filter U.S. colleges and universities) plus the filterable dimensions, and explicitly distinguishes itself from two siblings (scorecard_get_school for profiles, scorecard_search_programs for programs). An agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative tools and what each is for, and adds a real usage constraint (geographic distance requires a U.S. ZIP; ZIP alone falls back to the provider default radius). It does not state the inverse case (when not to use this tool if e.g. you already have a school ID), so it stops just short of fully explicit exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scorecard_value_analysisValue AnalysisARead-onlyInspect
Analyze costs, debt, repayment progress, and earnings for one school. Returns debt-to-earnings and net-price-to-annual-earnings ratios alongside the source figures. family_income selects the applicable net-price bracket. Repayment progress is the share of borrowers paying down principal 3 years after entering repayment.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | School ID from scorecard_search_schools. | |
| family_income | No | Annual family income in dollars. When provided, net price is shown for the applicable income bracket. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| ope6_id | No | Provider OPEID6 identifier, preserving leading zeros. |
| school_id | No | School unit ID. |
| data_notes | No | Flags for suppressed, missing, or potentially unreliable data fields. Empty when all data is available. |
| list_price | No | Effective tuition and fees; see tuition_basis for academic-year or program-year period. |
| median_debt | No | Median debt at graduation (completers). |
| school_name | No | Institution name. |
| metric_scope | No | Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific. |
| family_income | No | Requested annual family income in dollars. |
| tuition_basis | No | Period of the effective tuition. |
| graduation_rate | No | Completion rate at 150% normal time (0–1). |
| net_price_basis | No | Source of the effective price; unavailable means no estimate exists. |
| attendance_basis | No | Period of the effective attendance cost, selected independently of tuition. |
| effective_tuition | No | Available academic-year tuition, otherwise program-year tuition. |
| net_price_overall | No | Average net price across all income levels. |
| cost_of_attendance | No | Available academic-year attendance cost, otherwise program-year cost. |
| earnings_6yr_median | No | Median earnings 6 years after entry. |
| effective_net_price | No | Price used in the annual-earnings ratio: available income bracket, otherwise overall net price. |
| earnings_10yr_median | No | Median earnings 10 years after entry. |
| net_price_for_income | No | Net price for the provided family income bracket. Omitted when family_income not provided. |
| tuition_program_year | No | Reported program-year tuition and fees. |
| debt_to_earnings_ratio | No | Debt-to-earnings ratio: median_debt / earnings_6yr_median. Values >1 indicate debt exceeds annual earnings. |
| repayment_progress_3yr | No | Share of borrowers paying down principal (declining loan balance) 3 years after entering repayment (0–1). |
| attendance_program_year | No | Reported program-year cost of attendance. |
| applicable_income_bracket | No | Requested income bracket, retained even when its estimate is unavailable. |
| net_price_to_annual_earnings | No | Net price divided by median annual earnings measured 6 years after entry. Uses the family-income net price when available, otherwise the overall net price. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so safety is covered; the description adds real value on top by naming the returned ratios and source figures and by defining the otherwise-ambiguous 'repayment progress' as the share of borrowers paying down principal 3 years after entering repayment. It stops short of covering data vintage, coverage gaps, or error behavior for unknown IDs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with purpose then outputs, with no filler. The family_income sentence is mildly redundant with the schema, keeping it just below top marks.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return-value documentation is not required, yet the description still summarizes what comes back and defines the one metric whose meaning an agent could not infer. For a 2-parameter read-only tool with full schema coverage, nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters and the ID format in detail. The description's note that family_income selects the applicable net-price bracket largely restates the schema's own wording, adding little meaning beyond it; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Analyze') plus the exact resource set (costs, debt, repayment progress, earnings) scoped to 'one school', which cleanly separates it from scorecard_compare_schools (multi-school) and scorecard_get_earnings (earnings only). The second sentence further pins down the outputs (debt-to-earnings, net-price-to-annual-earnings ratios).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the single-school scope and the listed metrics suggest when to reach for this over compare_schools or get_earnings, but there is no explicit when-to-use, when-not, or named alternative. The one conditional behavior stated (family_income selects the net-price bracket) is parameter guidance rather than tool-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
- Changed
scorecard_compare_schools7 fields changed- changed
Input schema / properties / ids / descriptionPrevious value: -"Array of 2–5 school unit IDs to compare."New value: +"2–1,000 raw school IDs; first five distinct normalized IDs compared." - changed
Input schema / properties / ids / maxItemsPrevious value: -5New value: +1000 - added
Output schema / properties / missing_idsAdded value: +{ + "description": "Processed IDs without records.", + "items": { + "type": "number" + }, + "type": "array" +} - added
Output schema / properties / rows / items / properties / values / items / properties / basisAdded value: +{ + "description": "Period of an effective price.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / schools / items / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific.", + "properties": { + "completion": { + "const": "campus", + "description": "Completion is campus-specific.", + "type": "string" + }, + "debt": { + "const": "opeid6", + "description": "Debt is OPEID6-pooled.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings are OPEID6-pooled.", + "type": "string" + }, + "repayment": { + "const": "opeid6", + "description": "Repayment is OPEID6-pooled.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "repayment", + "completion" + ], + "type": "object" +} - added
Output schema / properties / schools / items / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 identifier, preserving leading zeros.", + "type": "string" +} - added
Output schema / properties / unprocessed_idsAdded value: +{ + "description": "Distinct normalized IDs beyond the five-school serving cap.", + "items": { + "type": "number" + }, + "type": "array" +}
- Changed
scorecard_get_earnings2 fields changed- added
Output schema / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific.", + "properties": { + "completion": { + "const": "campus", + "description": "Completion is campus-specific.", + "type": "string" + }, + "debt": { + "const": "opeid6", + "description": "Debt is OPEID6-pooled.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings are OPEID6-pooled.", + "type": "string" + }, + "repayment": { + "const": "opeid6", + "description": "Repayment is OPEID6-pooled.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "repayment", + "completion" + ], + "type": "object" +} - added
Output schema / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 identifier, preserving leading zeros.", + "type": "string" +}
- Changed
scorecard_get_programs28 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Program rows per response; values above 100 normalize to 100.", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / min_earnings / descriptionPrevious value: -"Minimum 1-year post-graduation median earnings filter."New value: +"Minimum completion-based one-year median earnings; no legacy fallback." - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Zero-based program row offset after filtering and stable earnings ordering.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "school_id", - "school_name", - "programs", - "total", - "suppressed_count", - "unavailable_count", - "query" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "ope6_id", + "metric_scope", + "provenance", + "shown", + "offset", + "limit", + "nextOffset", + "truncated", + "school_id", + "school_name", + "programs", + "total", + "suppressed_count", + "unavailable_count", + "query" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / limitAdded value: +{ + "description": "Effective program row limit, at most 100.", + "type": "number" +} - added
Output schema / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Metric aggregation scope within CIP and credential.", + "properties": { + "debt": { + "const": "opeid6", + "description": "Debt pools across campuses sharing OPEID6.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings pool across campuses sharing OPEID6.", + "type": "string" + }, + "ipeds_awards": { + "const": "campus", + "description": "Awards belong to the campus.", + "type": "string" + }, + "program_identity": { + "description": "Program dimensions retained within each pooled group.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "ipeds_awards", + "program_identity" + ], + "type": "object" +} - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Next program row offset, or null when exhausted.", + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / offsetAdded value: +{ + "description": "Effective zero-based program offset.", + "type": "number" +} - added
Output schema / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 group identifier, preserving leading zeros; null when absent.", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / programs / descriptionPrevious value: -"All programs matching the filters, sorted by earnings descending with unavailable or privacy-suppressed earnings last."New value: +"One page of matching programs, stably sorted by completion-based one-year earnings descending, with unavailable current earnings last." - added
Output schema / properties / programs / items / properties / completion_1yr_availabilityAdded value: +{ + "description": "Availability of completion-based one-year median earnings.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_1yr_countAdded value: +{ + "description": "Working and not enrolled completers in the one-year earnings population.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_1yr_count_availabilityAdded value: +{ + "description": "Availability of the matching one-year population count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_1yr_medianAdded value: +{ + "description": "Median earnings one year after completion, in the stated dollar year.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_4yr_availabilityAdded value: +{ + "description": "Availability of completion-based four-year median earnings.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_4yr_countAdded value: +{ + "description": "Working and not enrolled completers in the four-year earnings population.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_4yr_count_availabilityAdded value: +{ + "description": "Availability of the matching four-year population count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_4yr_medianAdded value: +{ + "description": "Median earnings four years after completion, in the stated dollar year.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / credential_level_codeAdded value: +{ + "description": "Provider numeric credential identity; the legacy credential_level field remains a display label.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / programs / items / properties / credential_titleAdded value: +{ + "description": "Provider credential title when reported.", + "type": "string" +} - added
Output schema / properties / programs / items / properties / earnings_count_availabilityAdded value: +{ + "description": "Availability of the legacy highest-credential population count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - changed
Output schema / properties / programs / items / requiredPrevious value: -[ - "code", - "credential_level", - "suppressed", - "earnings_availability" -]New value: +[ + "completion_1yr_availability", + "completion_1yr_count_availability", + "completion_4yr_availability", + "completion_4yr_count_availability", + "earnings_count_availability", + "code", + "credential_level", + "suppressed", + "earnings_availability" +] - added
Output schema / properties / provenanceAdded value: +{ + "additionalProperties": false, + "description": "Dictionary cohort, measurement, and dollar provenance for each population.", + "properties": { + "completion_1yr": { + "additionalProperties": false, + "description": "Current completion-based one-year series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "completion_4yr": { + "additionalProperties": false, + "description": "Current completion-based four-year series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "debt": { + "additionalProperties": false, + "description": "Debt provenance distinct from earnings.", + "properties": { + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "cohort": { + "description": "Pooled debt academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "population": { + "description": "Borrower population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "cohort", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "highest_credential_1yr": { + "additionalProperties": false, + "description": "Legacy highest-credential series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "ipeds_awards_year1": { + "additionalProperties": false, + "description": "First debt-cohort year awards.", + "properties": { + "academic_year": { + "description": "Academic year of awards.", + "type": "string" + }, + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "population": { + "description": "Awards population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "academic_year", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "ipeds_awards_year2": { + "additionalProperties": false, + "description": "Second debt-cohort year awards.", + "properties": { + "academic_year": { + "description": "Academic year of awards.", + "type": "string" + }, + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "population": { + "description": "Awards population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "academic_year", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "source": { + "description": "Official dictionary URL.", + "type": "string" + } + }, + "required": [ + "source", + "highest_credential_1yr", + "completion_1yr", + "completion_4yr", + "debt", + "ipeds_awards_year1", + "ipeds_awards_year2" + ], + "type": "object" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Program rows returned on this page.", + "type": "number" +} - changed
Output schema / properties / suppressed_count / descriptionPrevious value: -"Number of programs with confirmed privacy-suppressed earnings."New value: +"Matching programs with confirmed privacy-suppressed legacy highest-credential earnings, before row paging." - changed
Output schema / properties / total / descriptionPrevious value: -"Total programs returned after filtering."New value: +"Total matching programs before row pagination." - added
Output schema / properties / truncatedAdded value: +{ + "description": "More matching program rows remain.", + "type": "boolean" +} - changed
Output schema / properties / unavailable_count / descriptionPrevious value: -"Programs with unavailable earnings of unknown cause."New value: +"Matching programs with unavailable legacy highest-credential earnings of unknown cause, before row paging."
- Changed
scorecard_get_school12 fields changed- added
Input schema / properties / program_limitAdded value: +{ + "default": 20, + "description": "Projected program positions per parent array; values above 100 are clamped to 100.", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / program_offsetAdded value: +{ + "default": 0, + "description": "Zero-based position in each projected program parent array.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / schools / items / properties / attendance_basisAdded value: +{ + "description": "Period of the effective attendance cost, selected independently of tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / schools / items / properties / attendance_program_yearAdded value: +{ + "description": "Reported program-year cost of attendance.", + "type": "number" +} - changed
Output schema / properties / schools / items / properties / cost_of_attendance / descriptionPrevious value: -"Total cost of attendance per year."New value: +"Available academic-year attendance cost, otherwise program-year cost." - added
Output schema / properties / schools / items / properties / effective_tuitionAdded value: +{ + "description": "Available academic-year tuition, otherwise program-year tuition.", + "type": "number" +} - added
Output schema / properties / schools / items / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific.", + "properties": { + "completion": { + "const": "campus", + "description": "Completion is campus-specific.", + "type": "string" + }, + "debt": { + "const": "opeid6", + "description": "Debt is OPEID6-pooled.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings are OPEID6-pooled.", + "type": "string" + }, + "repayment": { + "const": "opeid6", + "description": "Repayment is OPEID6-pooled.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "repayment", + "completion" + ], + "type": "object" +} - added
Output schema / properties / schools / items / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 identifier, preserving leading zeros.", + "type": "string" +} - added
Output schema / properties / schools / items / properties / program_pagesAdded value: +{ + "description": "Per-parent program array paging in provider order; continuation applies to this school.", + "items": { + "additionalProperties": false, + "description": "One projected program parent page.", + "properties": { + "continuation": { + "additionalProperties": false, + "description": "Selectors to request for this school next.", + "properties": { + "program_limit": { + "description": "Effective page limit.", + "type": "number" + }, + "program_offset": { + "description": "Next requested position.", + "type": "number" + } + }, + "required": [ + "program_offset", + "program_limit" + ], + "type": "object" + }, + "nextOffset": { + "description": "Next position when more remain.", + "type": "number" + }, + "offset": { + "description": "Zero-based requested position.", + "type": "number" + }, + "parent_path": { + "description": "Provider program parent path.", + "type": "string" + }, + "shown": { + "description": "Positions returned.", + "type": "number" + }, + "total": { + "description": "Total provider positions before paging.", + "type": "number" + }, + "truncated": { + "description": "Whether positions remain after this page.", + "type": "boolean" + } + }, + "required": [ + "parent_path", + "total", + "offset", + "shown", + "truncated" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / schools / items / properties / tuition_basisAdded value: +{ + "description": "Period of the effective tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / schools / items / properties / tuition_program_yearAdded value: +{ + "description": "Reported program-year tuition and fees.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when any projected program parent has remaining positions.", + "type": "boolean" +}
- Changed
scorecard_lookup_cip6 fields changed- added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Zero-based offset into the complete relevance-ordered matches.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "query", - "results", - "totalMatches", - "queryContext", - "truncated", - "shown", - "cap" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "query", + "results", + "totalMatches", + "offset", + "queryContext", + "truncated", + "shown", + "cap" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Offset to request next; absent when no matches remain.", + "type": "number" +} - added
Output schema / properties / offsetAdded value: +{ + "description": "Zero-based offset of this result page.", + "type": "number" +} - added
Output schema / properties / queryContext / properties / offsetAdded value: +{ + "description": "Applied zero-based offset.", + "type": "number" +} - changed
Output schema / properties / queryContext / requiredPrevious value: -[ - "query", - "limit" -]New value: +[ + "query", + "limit", + "offset" +]
- Changed
scorecard_search_programs30 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Program rows per response; values above 100 normalize to 100.", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / min_earnings / descriptionPrevious value: -"Minimum 1-year median earnings, inclusive. Filters this school page locally and excludes unavailable earnings; school totals are unchanged."New value: +"Minimum completion-based one-year median earnings, inclusive, without legacy fallback; filters this school page locally while school totals remain unchanged." - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Zero-based row offset within the filtered and sorted school page.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "total", - "page", - "per_page", - "programs", - "total_programs", - "suppressed_count", - "unavailable_count", - "query", - "totalCount", - "truncated", - "shown", - "cap" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "metric_scope", + "provenance", + "shown", + "offset", + "limit", + "nextOffset", + "next", + "total", + "page", + "per_page", + "programs", + "total_programs", + "suppressed_count", + "unavailable_count", + "query", + "totalCount", + "truncated", + "schools_shown", + "cap" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / cap / descriptionPrevious value: -"The per_page limit that was applied."New value: +"The effective program row limit that was applied." - added
Output schema / properties / limitAdded value: +{ + "description": "Effective program row limit, at most 100.", + "type": "number" +} - added
Output schema / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Aggregation scope within CIP and credential identity.", + "properties": { + "debt": { + "const": "opeid6", + "description": "Debt pools across campuses sharing OPEID6.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings pool across campuses sharing OPEID6.", + "type": "string" + }, + "ipeds_awards": { + "const": "campus", + "description": "Awards belong to the campus.", + "type": "string" + }, + "program_identity": { + "description": "Program dimensions retained within each pooled group.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "ipeds_awards", + "program_identity" + ], + "type": "object" +} - added
Output schema / properties / nextAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "offset": { + "description": "Row offset to request on that school page.", + "type": "number" + }, + "page": { + "description": "School page to request.", + "type": "number" + } + }, + "required": [ + "page", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Continuation using the same selectors and limits; null when exhausted." +} - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Next row offset on this school page, or null when drained.", + "type": [ + "number", + "null" + ] +} - added
Output schema / properties / offsetAdded value: +{ + "description": "Effective zero-based row offset within this school page.", + "type": "number" +} - changed
Output schema / properties / programs / descriptionPrevious value: -"Program rows retain separate credential identities, sorted by earnings descending with unavailable or privacy-suppressed earnings last."New value: +"One page of program rows retaining credential identities, stably sorted by completion-based one-year earnings descending, with unavailable current earnings last." - added
Output schema / properties / programs / items / properties / completion_1yr_availabilityAdded value: +{ + "description": "Availability of completion-based one-year median earnings.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_1yr_countAdded value: +{ + "description": "Working and not enrolled completers in the one-year earnings population.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_1yr_count_availabilityAdded value: +{ + "description": "Availability of the matching one-year population count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_1yr_medianAdded value: +{ + "description": "Median earnings one year after completion, in the stated dollar year.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_4yr_availabilityAdded value: +{ + "description": "Availability of completion-based four-year median earnings.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_4yr_countAdded value: +{ + "description": "Working and not enrolled completers in the four-year earnings population.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / completion_4yr_count_availabilityAdded value: +{ + "description": "Availability of the matching four-year population count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / completion_4yr_medianAdded value: +{ + "description": "Median earnings four years after completion, in the stated dollar year.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / earnings_countAdded value: +{ + "description": "Legacy highest-credential working/not-enrolled population count.", + "type": "number" +} - added
Output schema / properties / programs / items / properties / earnings_count_availabilityAdded value: +{ + "description": "Availability of the legacy highest-credential count.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - added
Output schema / properties / programs / items / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 group identifier, preserving leading zeros; null when absent.", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / programs / items / requiredPrevious value: -[ - "school_id", - "school_name", - "school_ownership", - "program_code", - "suppressed", - "earnings_availability" -]New value: +[ + "completion_1yr_availability", + "completion_1yr_count_availability", + "completion_4yr_availability", + "completion_4yr_count_availability", + "ope6_id", + "earnings_count_availability", + "school_id", + "school_name", + "school_ownership", + "program_code", + "suppressed", + "earnings_availability" +] - added
Output schema / properties / provenanceAdded value: +{ + "additionalProperties": false, + "description": "Dictionary provenance for each distinct program population.", + "properties": { + "completion_1yr": { + "additionalProperties": false, + "description": "Current completion-based one-year series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "completion_4yr": { + "additionalProperties": false, + "description": "Current completion-based four-year series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "debt": { + "additionalProperties": false, + "description": "Debt provenance distinct from earnings.", + "properties": { + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "cohort": { + "description": "Pooled debt academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "population": { + "description": "Borrower population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "cohort", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "highest_credential_1yr": { + "additionalProperties": false, + "description": "Legacy highest-credential series.", + "properties": { + "cohort": { + "description": "Pooled completion academic years.", + "items": { + "description": "Academic year.", + "type": "string" + }, + "type": "array" + }, + "count_cell": { + "description": "Most-recent count map cell.", + "type": "string" + }, + "count_variable": { + "description": "Dictionary count variable.", + "type": "string" + }, + "dollar_year": { + "description": "Inflation-adjusted dollar year.", + "type": "number" + }, + "measurement_years": { + "description": "Earnings measurement calendar years.", + "items": { + "description": "Calendar year.", + "type": "number" + }, + "type": "array" + }, + "median_cell": { + "description": "Most-recent median map cell.", + "type": "string" + }, + "median_variable": { + "description": "Dictionary median variable.", + "type": "string" + }, + "population": { + "description": "Population represented.", + "type": "string" + } + }, + "required": [ + "cohort", + "measurement_years", + "dollar_year", + "median_variable", + "count_variable", + "median_cell", + "count_cell", + "population" + ], + "type": "object" + }, + "ipeds_awards_year1": { + "additionalProperties": false, + "description": "First debt-cohort year awards.", + "properties": { + "academic_year": { + "description": "Academic year of awards.", + "type": "string" + }, + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "population": { + "description": "Awards population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "academic_year", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "ipeds_awards_year2": { + "additionalProperties": false, + "description": "Second debt-cohort year awards.", + "properties": { + "academic_year": { + "description": "Academic year of awards.", + "type": "string" + }, + "cell": { + "description": "Most-recent map cell.", + "type": "string" + }, + "population": { + "description": "Awards population.", + "type": "string" + }, + "variable": { + "description": "Dictionary variable.", + "type": "string" + } + }, + "required": [ + "academic_year", + "variable", + "cell", + "population" + ], + "type": "object" + }, + "source": { + "description": "Official dictionary URL.", + "type": "string" + } + }, + "required": [ + "source", + "highest_credential_1yr", + "completion_1yr", + "completion_4yr", + "debt", + "ipeds_awards_year1", + "ipeds_awards_year2" + ], + "type": "object" +} - added
Output schema / properties / schools_shownAdded value: +{ + "description": "Schools returned on this school page.", + "type": "number" +} - changed
Output schema / properties / shown / descriptionPrevious value: -"Schools returned on this page."New value: +"Program rows returned in this response." - changed
Output schema / properties / suppressed_count / descriptionPrevious value: -"Programs with suppressed earnings."New value: +"Matching programs with confirmed privacy-suppressed legacy highest-credential earnings, before row paging." - changed
Output schema / properties / total_programs / descriptionPrevious value: -"Total programs returned across all result schools."New value: +"Matching program rows on the fetched school page before row pagination." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when school pagination metadata indicates a later page exists."New value: +"True when more program rows or a later school page remain." - changed
Output schema / properties / unavailable_count / descriptionPrevious value: -"Programs with unavailable earnings of unknown cause."New value: +"Matching programs with unavailable legacy highest-credential earnings of unknown cause, before row paging."
- Changed
scorecard_search_schools9 fields changed- changed
Input schema / properties / degree_level / descriptionPrevious value: -"Predominant degree: 0=non-degree/certificate, 1=certificate, 2=associate, 3=bachelor, 4=graduate."New value: +"Predominant degree: 0=Not classified, 1=certificate, 2=associate, 3=bachelor, 4=Entirely graduate-degree granting." - added
Output schema / properties / schools / items / properties / attendance_basisAdded value: +{ + "description": "Period of the effective attendance cost, selected independently of tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / schools / items / properties / attendance_program_yearAdded value: +{ + "description": "Reported program-year cost of attendance.", + "type": "number" +} - added
Output schema / properties / schools / items / properties / cost_of_attendanceAdded value: +{ + "description": "Available academic-year attendance cost, otherwise program-year cost.", + "type": "number" +} - added
Output schema / properties / schools / items / properties / effective_tuitionAdded value: +{ + "description": "Available academic-year tuition, otherwise program-year tuition.", + "type": "number" +} - added
Output schema / properties / schools / items / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific.", + "properties": { + "completion": { + "const": "campus", + "description": "Completion is campus-specific.", + "type": "string" + }, + "debt": { + "const": "opeid6", + "description": "Debt is OPEID6-pooled.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings are OPEID6-pooled.", + "type": "string" + }, + "repayment": { + "const": "opeid6", + "description": "Repayment is OPEID6-pooled.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "repayment", + "completion" + ], + "type": "object" +} - added
Output schema / properties / schools / items / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 identifier, preserving leading zeros.", + "type": "string" +} - added
Output schema / properties / schools / items / properties / tuition_basisAdded value: +{ + "description": "Period of the effective tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / schools / items / properties / tuition_program_yearAdded value: +{ + "description": "Reported program-year tuition and fees.", + "type": "number" +}
- Changed
scorecard_value_analysis9 fields changed- added
Output schema / properties / attendance_basisAdded value: +{ + "description": "Period of the effective attendance cost, selected independently of tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / attendance_program_yearAdded value: +{ + "description": "Reported program-year cost of attendance.", + "type": "number" +} - added
Output schema / properties / cost_of_attendanceAdded value: +{ + "description": "Available academic-year attendance cost, otherwise program-year cost.", + "type": "number" +} - added
Output schema / properties / effective_tuitionAdded value: +{ + "description": "Available academic-year tuition, otherwise program-year tuition.", + "type": "number" +} - changed
Output schema / properties / list_price / descriptionPrevious value: -"Full tuition and fees (in-state, or out-of-state when no in-state exists)."New value: +"Effective tuition and fees; see tuition_basis for academic-year or program-year period." - added
Output schema / properties / metric_scopeAdded value: +{ + "additionalProperties": false, + "description": "Earnings, debt and repayment are pooled at OPEID6; completion is campus-specific.", + "properties": { + "completion": { + "const": "campus", + "description": "Completion is campus-specific.", + "type": "string" + }, + "debt": { + "const": "opeid6", + "description": "Debt is OPEID6-pooled.", + "type": "string" + }, + "earnings": { + "const": "opeid6", + "description": "Earnings are OPEID6-pooled.", + "type": "string" + }, + "repayment": { + "const": "opeid6", + "description": "Repayment is OPEID6-pooled.", + "type": "string" + } + }, + "required": [ + "earnings", + "debt", + "repayment", + "completion" + ], + "type": "object" +} - added
Output schema / properties / ope6_idAdded value: +{ + "description": "Provider OPEID6 identifier, preserving leading zeros.", + "type": "string" +} - added
Output schema / properties / tuition_basisAdded value: +{ + "description": "Period of the effective tuition.", + "enum": [ + "academic_year", + "program_year" + ], + "type": "string" +} - added
Output schema / properties / tuition_program_yearAdded value: +{ + "description": "Reported program-year tuition and fees.", + "type": "number" +}
5 tool updates
- Changed
scorecard_compare_schools3 fields changed- added
Output schema / properties / rows / items / properties / values / items / properties / availabilityAdded value: +{ + "description": "Available number, unavailable with unknown cause, or confirmed privacy suppression.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - changed
Output schema / properties / rows / items / properties / values / items / properties / suppressed / descriptionPrevious value: -"True when data is unavailable for this school/metric."New value: +"True only for explicit provider privacy markers." - changed
Output schema / properties / rows / items / properties / values / items / requiredPrevious value: -[ - "school_id", - "suppressed" -]New value: +[ + "school_id", + "suppressed", + "availability" +]
- Changed
scorecard_get_earnings18 fields changed- changed
Input schema / properties / years / descriptionPrevious value: -"Optional list of cohort entry years for historical trend data (e.g. [2011, 2012, 2013]). Omit for current snapshot."New value: +"Optional API data-file start years from 1996–2025 (e.g. [2003, 2011, 2020]); valid files may lack observations. Omit or pass [] for snapshot only." - added
Input schema / properties / years / items / descriptionAdded value: +"Published API data-file start year (1996–2025)." - changed
Input schema / properties / years / items / maximumPrevious value: -9007199254740991New value: +2025 - changed
Input schema / properties / years / items / minimumPrevious value: --9007199254740991New value: +1996 - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "school_id", - "school_name", - "current", - "suppressed" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "school_id", + "school_name", + "current_availability", + "current_context", + "current", + "suppressed" + ] + }, + { + "required": [ + "error" + ] + } +] - removed
Output schema / properties / current / properties / earnings_6yr_female_medianRemoved value: -{ - "description": "Median earnings 6 years after entry for female students.", - "type": "number" -} - added
Output schema / properties / current / properties / earnings_6yr_non_male_medianAdded value: +{ + "description": "Median earnings 6 years after entry for non-male students.", + "type": "number" +} - added
Output schema / properties / current_availabilityAdded value: +{ + "additionalProperties": { + "description": "Provider availability for one supported metric.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" + }, + "description": "Availability keyed by every supported current earnings metric.", + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / current_contextAdded value: +{ + "additionalProperties": { + "additionalProperties": false, + "description": "Official provenance for one metric.", + "properties": { + "data_file_year": { + "description": "Start year of the API data file; not a cohort entry year.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "dollar_year": { + "description": "Verified inflation dollar basis; returned values are not re-inflated.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entry_cohorts": { + "description": "Verified academic-year entry cohorts.", + "items": { + "type": "string" + }, + "type": "array" + }, + "measurement_years": { + "description": "Verified calendar years when earnings were measured.", + "items": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "data_file_year" + ], + "type": "object" + }, + "description": "Official latest provenance keyed by metric, independent of returned values.", + "propertyNames": { + "type": "string" + }, + "type": "object" +} - changed
Output schema / properties / suppressed / descriptionPrevious value: -"True when earnings data is suppressed across all time points."New value: +"True only when every supported current metric has an explicit privacy marker." - changed
Output schema / properties / trend / descriptionPrevious value: -"Historical trend rows by cohort entry year. Present only when years parameter was supplied."New value: +"Historical rows by API data-file start year. Present only when nonempty years were supplied." - changed
Output schema / properties / trend / items / descriptionPrevious value: -"Earnings data point for one cohort entry year."New value: +"Earnings observations for one API data file." - added
Output schema / properties / trend / items / properties / availabilityAdded value: +{ + "additionalProperties": { + "description": "Provider availability for one supported metric.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" + }, + "description": "Availability of the supported historical medians.", + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / trend / items / properties / contextAdded value: +{ + "additionalProperties": { + "additionalProperties": false, + "description": "Official provenance for one metric.", + "properties": { + "data_file_year": { + "description": "Start year of the API data file; not a cohort entry year.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "dollar_year": { + "description": "Verified inflation dollar basis; returned values are not re-inflated.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entry_cohorts": { + "description": "Verified academic-year entry cohorts.", + "items": { + "type": "string" + }, + "type": "array" + }, + "measurement_years": { + "description": "Verified calendar years when earnings were measured.", + "items": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "data_file_year" + ], + "type": "object" + }, + "description": "Verified per-metric provenance; unknown metadata omitted.", + "propertyNames": { + "type": "string" + }, + "type": "object" +} - changed
Output schema / properties / trend / items / properties / earnings_10yr_median / descriptionPrevious value: -"Median earnings 10 years after entry for this cohort."New value: +"Median earnings 10 years after entry reported in this data file." - changed
Output schema / properties / trend / items / properties / earnings_6yr_median / descriptionPrevious value: -"Median earnings 6 years after entry for this cohort."New value: +"Median earnings 6 years after entry reported in this data file." - changed
Output schema / properties / trend / items / properties / year / descriptionPrevious value: -"Cohort entry year."New value: +"API data-file start year." - changed
Output schema / properties / trend / items / requiredPrevious value: -[ - "year" -]New value: +[ + "year", + "availability", + "context" +]
- Changed
scorecard_get_programs8 fields changed- changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "school_id", - "school_name", - "programs", - "total", - "suppressed_count", - "query" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "school_id", + "school_name", + "programs", + "total", + "suppressed_count", + "unavailable_count", + "query" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no programs match the filters or all data is suppressed."New value: +"Guidance when no programs match or some earnings are unavailable or privacy-suppressed." - changed
Output schema / properties / programs / descriptionPrevious value: -"All programs at this school matching the filters. Sorted by median earnings descending (suppressed programs at end)."New value: +"All programs matching the filters, sorted by earnings descending with unavailable or privacy-suppressed earnings last." - added
Output schema / properties / programs / items / properties / earnings_availabilityAdded value: +{ + "description": "Available number, unavailable with unknown cause, or confirmed privacy suppression.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - changed
Output schema / properties / programs / items / properties / suppressed / descriptionPrevious value: -"True when earnings data is suppressed due to small cohort (FERPA)."New value: +"True only when the provider explicitly marks earnings as privacy-suppressed." - changed
Output schema / properties / programs / items / requiredPrevious value: -[ - "code", - "credential_level", - "suppressed" -]New value: +[ + "code", + "credential_level", + "suppressed", + "earnings_availability" +] - changed
Output schema / properties / suppressed_count / descriptionPrevious value: -"Number of programs with earnings suppressed due to small cohort."New value: +"Number of programs with confirmed privacy-suppressed earnings." - added
Output schema / properties / unavailable_countAdded value: +{ + "description": "Programs with unavailable earnings of unknown cause.", + "type": "number" +}
- Changed
scorecard_search_programs9 fields changed- added
Input schema / properties / credential_levelAdded value: +{ + "description": "Provider credential selector: 1=undergraduate certificate, 2=associate, 3=bachelor, 4=post-baccalaureate certificate, 5=master, 6=doctoral, 7=first professional, 8=graduate/professional certificate, 99=non-credential; other integer levels may return no matches.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "total", - "page", - "per_page", - "programs", - "total_programs", - "suppressed_count", - "query", - "totalCount", - "truncated", - "shown", - "cap" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "total", + "page", + "per_page", + "programs", + "total_programs", + "suppressed_count", + "unavailable_count", + "query", + "totalCount", + "truncated", + "shown", + "cap" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / programs / descriptionPrevious value: -"Program results — multiple programs per school if school matches multiple CIP codes. Sorted by earnings descending (suppressed last)."New value: +"Program rows retain separate credential identities, sorted by earnings descending with unavailable or privacy-suppressed earnings last." - added
Output schema / properties / programs / items / properties / credential_levelAdded value: +{ + "description": "Provider credential level; unknown future numeric levels are retained.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / programs / items / properties / credential_titleAdded value: +{ + "description": "Provider credential title, when reported.", + "type": "string" +} - added
Output schema / properties / programs / items / properties / earnings_availabilityAdded value: +{ + "description": "Available number, unavailable with unknown cause, or confirmed privacy suppression.", + "enum": [ + "available", + "unavailable", + "privacy_suppressed" + ], + "type": "string" +} - changed
Output schema / properties / programs / items / properties / suppressed / descriptionPrevious value: -"True when earnings are suppressed due to small cohort."New value: +"True only for explicit provider privacy markers." - changed
Output schema / properties / programs / items / requiredPrevious value: -[ - "school_id", - "school_name", - "school_ownership", - "program_code", - "suppressed" -]New value: +[ + "school_id", + "school_name", + "school_ownership", + "program_code", + "suppressed", + "earnings_availability" +] - added
Output schema / properties / unavailable_countAdded value: +{ + "description": "Programs with unavailable earnings of unknown cause.", + "type": "number" +}
- Changed
scorecard_value_analysis5 fields changed- changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "school_id", - "school_name", - "data_notes" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "school_id", + "school_name", + "net_price_basis", + "data_notes" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / applicable_income_bracket / descriptionPrevious value: -"Income bracket used for net_price_for_income."New value: +"Requested income bracket, retained even when its estimate is unavailable." - added
Output schema / properties / effective_net_priceAdded value: +{ + "description": "Price used in the annual-earnings ratio: available income bracket, otherwise overall net price.", + "type": "number" +} - added
Output schema / properties / family_incomeAdded value: +{ + "description": "Requested annual family income in dollars.", + "type": "number" +} - added
Output schema / properties / net_price_basisAdded value: +{ + "description": "Source of the effective price; unavailable means no estimate exists.", + "enum": [ + "income_bracket", + "overall", + "unavailable" + ], + "type": "string" +}
9 tool updates
- First observed
scorecard_compare_schools - First observed
scorecard_get_earnings - First observed
scorecard_get_programs - First observed
scorecard_get_school - First observed
scorecard_list_fields - First observed
scorecard_lookup_cip - First observed
scorecard_search_programs - First observed
scorecard_search_schools - First observed
scorecard_value_analysis
Related MCP Connectors
Search US colleges and compare historical admissions, costs and aid using public federal data.
Higher education data: tuition, graduation rates, and earnings
Admission chances at 1,100+ U.S. colleges, college list scoring, and federal admissions data.
Compare state 529 plans, look up college costs and check qualified 529 expenses. Free, no key.
Related MCP Servers
- AlicenseAqualityDmaintenanceSearches US colleges and scholarships using government data, enabling comparisons of tuition, debt, earnings, and program-specific outcomes.4MIT
- AlicenseNot gradedqualityBmaintenanceProvides read-only access to U.S. college and major ROI data, enabling queries for lifetime returns, 30-year NPV, break-even ages, best-value colleges, and out-of-state penalties through MCP tools.MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to explore, compare, and engage with postsecondary education and training offerings—programs, courses, certifications, credit transfer, prior learning, and career transitions—with sourced, snapshot-dated answers and explicit statements of missing data.-
- AlicenseNot gradedqualityBmaintenanceCollege Scorecard MCP — US Department of Education College Scorecard API13 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.