@cyanheads/college-scorecard-mcp-server
Search, compare, and analyze U.S. college data — costs, earnings, programs, and outcomes — via MCP. STDIO or Streamable HTTP.
9 Tools • 3 Resources • 1 Prompt • 1 Skill
Overview
US college data from the Department of Education College Scorecard: costs, earnings, programs, and outcomes across roughly 6,500 institutions. Search and compare schools, look up earnings by field of study, and compute ROI metrics like debt-to-earnings ratio.
Tools
Resources
All resource data is also reachable via tools. Use scorecard_search_schools or scorecard_get_school to discover school IDs before constructing resource URIs.
The college-scorecard-guide covers campus/CIP identity, paging, outcome populations, OPEID6 pooling, and price-basis gates. It ships with plugins, npm, Docker, and MCPB, and is served through the MCP Skills extension.
Prompts
Capability reference
scorecard_search_schools tool
- Search by name, state, ownership, degree level, size, acceptance rate, CIP code, or ZIP and distance (miles or
km). per_page is capped at 100; page is zero-indexed. State lists accept WA,CA.
- Returns core identity and cost metrics for quick scanning.
sort takes an API expression such as latest.cost.avg_net_price.overall:asc (:desc reverses it). men_only and women_only accept true or false.
scorecard_get_school tool
- Accepts a school ID or an array of up to 1,000. The first 100 distinct IDs are fetched;
missing_ids lists fetched IDs with no record and unprocessed_ids lists the excess.
- Default profiles cover costs, admissions, outcomes, financial aid, demographics, and completion rates. Custom
fields returns selected_fields with the requested values, and absent_fields lists requested paths missing from the response.
- Projected program arrays use
program_limit (default 20, capped at 100) and program_offset; follow each school's program_pages continuation. Raw values and provider positions stay aligned.
- HBCU and single-sex flags are true/false when known and unknown when absent.
scorecard_compare_schools tool
- Accepts 2–1,000 raw unit IDs and compares the first five distinct normalized IDs on
costs, admissions, outcomes, or aid. missing_ids were queried; unprocessed_ids were not.
- Equal independent values share a rank (1, 1, 3). Missing values, pooled outcome rows containing shared OPEID6 groups, and mixed academic/program-year price rows are unranked.
- Each cell's
availability distinguishes available, unavailable, and privacy-suppressed values.
scorecard_get_programs tool
- Accepts one school ID, with optional CIP code (dotted or undotted),
credential_level, and minimum earnings filters. A school with no matching programs returns an empty collection; a nonexistent school is a lookup error.
- Completion-based 1/4-year medians and counts carry separate availability and provenance. Legacy
earnings_1yr_median/earnings_count retain highest-credential semantics; their availability and suppression counts remain separate.
min_earnings and ordering use completion-based one-year earnings, with no legacy fallback. Page with limit (default 20, capped at 100) and offset; total counts matches before paging, and nextOffset is null at the end.
median_debt is completers' cumulative Stafford/Grad PLUS borrowing. ipeds_awards_year1 and ipeds_awards_year2 count awards in each year of the pooled debt cohort, not students.
scorecard_search_programs tool
- Search by CIP code or program name, with optional integer
credential_level (1–8 and 99), state, ownership, net price, earnings, and debt filters. page/per_page paginate schools; offset/limit page matching program rows within that school page.
- Returns school IDs and names with program metrics,
credential_level, and credential_title. Available earnings sort first; availability, debt, and award fields match scorecard_get_programs.
min_earnings filters locally, so totals and pagination are upstream school counts before filtering. Earnings and debt thresholds are inclusive and exclude unknown values.
- Follow
next until null: it drains program rows on the current school page before advancing. shown counts returned programs; schools_shown counts fetched schools. Rankings use current completion-based one-year earnings within the fetched page only.
scorecard_get_earnings tool
- Accepts one school ID and optional data-file start
years from 1996–2025 (file vintages, not entry years). Omit years or pass [] for the snapshot only.
- Covers federally aided undergraduate entrants working and not enrolled, regardless of completion: medians at 6/8/10 years after entry, 6/10-year P25/P75, and non-male/male 6-year medians.
current_availability and trend[].availability classify each metric. current_context and trend[].context give data_file_year, entry_cohorts, measurement_years, and dollar_year; values keep the provider's dollar basis, so check it before comparing across vintages.
scorecard_value_analysis tool
- Accepts one school ID; optional
family_income selects the applicable net price bracket ($0–30k, $30k–48k, $48k–75k, $75k–110k, or $110k+).
- Returns ratios alongside their source figures.
effective_net_price is the price used, and net_price_basis is income_bracket, overall, or unavailable.
- If the bracket is missing, the overall price is used and
data_notes says so. Ratios require positive annual earnings.
- Tuition and attendance independently prefer academic-year prices, otherwise reported program-year prices; each has its own basis. Program tuition never substitutes for net price. OPEID6-pooled outcomes are identified alongside campus prices.
scorecard_lookup_cip tool
- Search by nonblank keyword or partial name (default limit 20, capped at 50). Dotted
11.07 and undotted 1107 are equivalent; continue with offset and returned nextOffset while more results remain.
- Returns exact group titles and family identities from all 464 current NCES CIP 2020 four-digit groups. Verified six-digit program aliases return their group; no matches return an empty collection with guidance.
scorecard_list_fields tool
- Search 84 curated offline field entries by nonblank query (default limit 30, capped at 100). Use before passing custom
fields to scorecard_get_school.
- Returns field paths, descriptions, data types, categories, and API sorting support;
tip flags results containing unsortable fields.
scorecard://school/{id} resource
- Institutional profile as
application/json — identity, cost, admissions, outcomes, aid, and completion data
id is the school unit ID (integer as string) from scorecard_search_schools
list returns a handful of example school URIs; use scorecard_search_schools to discover others
scorecard://programs/{id} resource
- First 20 program rows as
application/json, in provider order, with current/legacy earnings populations, scope, provenance, debt, and campus awards. Legacy nullable metrics retain null; new metrics expose availability.
id is the school unit ID from scorecard_search_schools
list returns a handful of example school URIs; use scorecard_search_schools to discover others
- Follow
nextUri through scorecard://programs/{id}/page/{offset}/{limit} until null. Page limits above 100 normalize to 100, with a hard ceiling of 1,000; offsets are zero-based. Tool ordering differs, so do not reuse offsets between tools and resources.
scorecard_compare_prompt prompt
- Arguments:
school_names (comma-separated list) and focus (costs | outcomes | programs), both required
costs and outcomes run school discovery, scorecard_compare_schools, profiles, and value analysis. programs runs school discovery, CIP lookup, and scorecard_get_programs per school, then compares earnings, debt, and IPEDS awards for matching credentials.
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
College Scorecard-specific:
- Full College Scorecard API coverage: ~6,500 Title IV institutions, ~2,800 data fields spanning costs, outcomes, demographics, financial aid, and field-of-study earnings
- Program completion earnings at one and four years, alongside legacy highest-credential outcomes; each series carries its population and vintage
- Field pre-selection per tool — curated field sets appropriate to each tool's purpose; optional
fields override for custom queries
- Embedded CIP taxonomy (464 groups) and field catalog (84 fields) served offline
- Geographic filtering via U.S. zip code + distance radius
Agent-friendly output:
- Availability distinguishes numbers (including zero), missing values, and explicit
PS / PrivacySuppressed provider markers
- Derived metrics sit alongside source figures in
scorecard_value_analysis, and scorecard_compare_schools adds ordinal ranks
- School sorting uses indexed API fields; check
scorecard_list_fields before choosing a sort expression. Six-year earnings does not support API sorting.
- Provider failures report distinct validation, authentication, throttling, timeout, and availability reasons; availability uses
api_error and cancellation remains RequestCancelled
Getting started
Public Hosted Instance
A public instance is available at https://college-scorecard.caseyjhand.com/mcp — no installation required. No API key needed; the instance supplies its own. Point any MCP client at it via Streamable HTTP:
Self-Hosted / Local
Add the following to your MCP client configuration file. See api.data.gov/signup for a free API key.
Or with npx (no Bun required):
Or with Docker:
For Streamable HTTP, set the transport and start the server:
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- A College Scorecard API key — free registration at api.data.gov/signup. Rate limit: 1,000 requests/hour per key.
Installation
- Clone the repository:
- Navigate into the directory:
- Install dependencies:
- Configure environment:
Configuration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run:
-
Run checks and tests:
Docker
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/college-scorecard-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catch in tool logic
- Use
ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
- Register new tools, resources, and prompts in the
createApp() arrays in src/index.ts
- Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
- During maintenance, run
bun run check:earnings-provenance (Python 3 required) to compare embedded institution earnings metadata with the official dictionary. Pass a local XLSX path to reuse a download; requests never fetch the dictionary.
Contributing
Issues are welcome. Run checks and tests before submitting:
License
Apache-2.0 — see LICENSE for details.