@cyanheads/college-scorecard-mcp-server 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CLAUDE.md +405 -0
  2. package/Dockerfile +98 -0
  3. package/README.md +356 -0
  4. package/changelog/0.1.x/0.1.0.md +24 -0
  5. package/changelog/0.1.x/0.1.1.md +14 -0
  6. package/changelog/template.md +119 -0
  7. package/dist/config/server-config.d.ts +12 -0
  8. package/dist/config/server-config.d.ts.map +1 -0
  9. package/dist/config/server-config.js +17 -0
  10. package/dist/config/server-config.js.map +1 -0
  11. package/dist/data/cip-codes.d.ts +23 -0
  12. package/dist/data/cip-codes.d.ts.map +1 -0
  13. package/dist/data/cip-codes.js +274 -0
  14. package/dist/data/cip-codes.js.map +1 -0
  15. package/dist/data/field-catalog.d.ts +25 -0
  16. package/dist/data/field-catalog.d.ts.map +1 -0
  17. package/dist/data/field-catalog.js +122 -0
  18. package/dist/data/field-catalog.js.map +1 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +47 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/mcp-server/format-helpers.d.ts +9 -0
  24. package/dist/mcp-server/format-helpers.d.ts.map +1 -0
  25. package/dist/mcp-server/format-helpers.js +24 -0
  26. package/dist/mcp-server/format-helpers.js.map +1 -0
  27. package/dist/mcp-server/prompts/definitions/compare.prompt.d.ts +15 -0
  28. package/dist/mcp-server/prompts/definitions/compare.prompt.d.ts.map +1 -0
  29. package/dist/mcp-server/prompts/definitions/compare.prompt.js +55 -0
  30. package/dist/mcp-server/prompts/definitions/compare.prompt.js.map +1 -0
  31. package/dist/mcp-server/resources/definitions/programs.resource.d.ts +10 -0
  32. package/dist/mcp-server/resources/definitions/programs.resource.d.ts.map +1 -0
  33. package/dist/mcp-server/resources/definitions/programs.resource.js +42 -0
  34. package/dist/mcp-server/resources/definitions/programs.resource.js.map +1 -0
  35. package/dist/mcp-server/resources/definitions/school.resource.d.ts +10 -0
  36. package/dist/mcp-server/resources/definitions/school.resource.d.ts.map +1 -0
  37. package/dist/mcp-server/resources/definitions/school.resource.js +43 -0
  38. package/dist/mcp-server/resources/definitions/school.resource.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/compare-schools.tool.d.ts +46 -0
  40. package/dist/mcp-server/tools/definitions/compare-schools.tool.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/compare-schools.tool.js +367 -0
  42. package/dist/mcp-server/tools/definitions/compare-schools.tool.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/get-earnings.tool.d.ts +43 -0
  44. package/dist/mcp-server/tools/definitions/get-earnings.tool.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/get-earnings.tool.js +183 -0
  46. package/dist/mcp-server/tools/definitions/get-earnings.tool.js.map +1 -0
  47. package/dist/mcp-server/tools/definitions/get-programs.tool.d.ts +46 -0
  48. package/dist/mcp-server/tools/definitions/get-programs.tool.d.ts.map +1 -0
  49. package/dist/mcp-server/tools/definitions/get-programs.tool.js +194 -0
  50. package/dist/mcp-server/tools/definitions/get-programs.tool.js.map +1 -0
  51. package/dist/mcp-server/tools/definitions/get-school.tool.d.ts +67 -0
  52. package/dist/mcp-server/tools/definitions/get-school.tool.d.ts.map +1 -0
  53. package/dist/mcp-server/tools/definitions/get-school.tool.js +324 -0
  54. package/dist/mcp-server/tools/definitions/get-school.tool.js.map +1 -0
  55. package/dist/mcp-server/tools/definitions/list-fields.tool.d.ts +28 -0
  56. package/dist/mcp-server/tools/definitions/list-fields.tool.d.ts.map +1 -0
  57. package/dist/mcp-server/tools/definitions/list-fields.tool.js +92 -0
  58. package/dist/mcp-server/tools/definitions/list-fields.tool.js.map +1 -0
  59. package/dist/mcp-server/tools/definitions/lookup-cip.tool.d.ts +26 -0
  60. package/dist/mcp-server/tools/definitions/lookup-cip.tool.d.ts.map +1 -0
  61. package/dist/mcp-server/tools/definitions/lookup-cip.tool.js +71 -0
  62. package/dist/mcp-server/tools/definitions/lookup-cip.tool.js.map +1 -0
  63. package/dist/mcp-server/tools/definitions/search-programs.tool.d.ts +49 -0
  64. package/dist/mcp-server/tools/definitions/search-programs.tool.d.ts.map +1 -0
  65. package/dist/mcp-server/tools/definitions/search-programs.tool.js +188 -0
  66. package/dist/mcp-server/tools/definitions/search-programs.tool.js.map +1 -0
  67. package/dist/mcp-server/tools/definitions/search-schools.tool.d.ts +57 -0
  68. package/dist/mcp-server/tools/definitions/search-schools.tool.d.ts.map +1 -0
  69. package/dist/mcp-server/tools/definitions/search-schools.tool.js +223 -0
  70. package/dist/mcp-server/tools/definitions/search-schools.tool.js.map +1 -0
  71. package/dist/mcp-server/tools/definitions/value-analysis.tool.d.ts +37 -0
  72. package/dist/mcp-server/tools/definitions/value-analysis.tool.d.ts.map +1 -0
  73. package/dist/mcp-server/tools/definitions/value-analysis.tool.js +227 -0
  74. package/dist/mcp-server/tools/definitions/value-analysis.tool.js.map +1 -0
  75. package/dist/services/scorecard/scorecard-service.d.ts +44 -0
  76. package/dist/services/scorecard/scorecard-service.d.ts.map +1 -0
  77. package/dist/services/scorecard/scorecard-service.js +376 -0
  78. package/dist/services/scorecard/scorecard-service.js.map +1 -0
  79. package/dist/services/scorecard/types.d.ts +131 -0
  80. package/dist/services/scorecard/types.d.ts.map +1 -0
  81. package/dist/services/scorecard/types.js +6 -0
  82. package/dist/services/scorecard/types.js.map +1 -0
  83. package/package.json +80 -0
  84. package/server.json +99 -0
@@ -0,0 +1,376 @@
1
+ /**
2
+ * @fileoverview College Scorecard API service. Wraps the api.data.gov/ed/collegescorecard/v1
3
+ * endpoint with retry, field selection, and pagination support.
4
+ * @module services/scorecard/scorecard-service
5
+ */
6
+ import { notFound, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
7
+ import { withRetry } from '@cyanheads/mcp-ts-core/utils';
8
+ import { getServerConfig } from '../../config/server-config.js';
9
+ const BASE_URL = 'https://api.data.gov/ed/collegescorecard/v1/schools';
10
+ /** Default curated fields for school search results */
11
+ const SEARCH_DEFAULT_FIELDS = [
12
+ 'id',
13
+ 'school.name',
14
+ 'school.city',
15
+ 'school.state',
16
+ 'school.ownership',
17
+ 'school.degrees_awarded.predominant',
18
+ 'latest.student.size',
19
+ 'latest.admissions.admission_rate.overall',
20
+ 'latest.cost.tuition.in_state',
21
+ 'latest.cost.tuition.out_of_state',
22
+ 'latest.cost.avg_net_price.overall',
23
+ 'latest.aid.median_debt.completers.overall',
24
+ 'latest.earnings.6_yrs_after_entry.median',
25
+ ].join(',');
26
+ /** Default fields for full school profile */
27
+ const PROFILE_DEFAULT_FIELDS = [
28
+ 'id',
29
+ 'school.name',
30
+ 'school.city',
31
+ 'school.state',
32
+ 'school.zip',
33
+ 'school.school_url',
34
+ 'school.ownership',
35
+ 'school.carnegie_basic',
36
+ 'school.locale',
37
+ 'school.degrees_awarded.predominant',
38
+ 'school.hbcu',
39
+ 'school.men_only',
40
+ 'school.women_only',
41
+ 'latest.student.size',
42
+ 'latest.admissions.admission_rate.overall',
43
+ 'latest.admissions.sat_scores.average.overall',
44
+ 'latest.admissions.sat_scores.25th_percentile.critical_reading',
45
+ 'latest.admissions.sat_scores.75th_percentile.critical_reading',
46
+ 'latest.admissions.sat_scores.25th_percentile.math',
47
+ 'latest.admissions.sat_scores.75th_percentile.math',
48
+ 'latest.admissions.act_scores.25th_percentile.cumulative',
49
+ 'latest.admissions.act_scores.75th_percentile.cumulative',
50
+ 'latest.cost.tuition.in_state',
51
+ 'latest.cost.tuition.out_of_state',
52
+ 'latest.cost.avg_net_price.overall',
53
+ 'latest.cost.avg_net_price.by_income.0-30000',
54
+ 'latest.cost.avg_net_price.by_income.30001-48000',
55
+ 'latest.cost.avg_net_price.by_income.48001-75000',
56
+ 'latest.cost.avg_net_price.by_income.75001-110000',
57
+ 'latest.cost.avg_net_price.by_income.110001-plus',
58
+ 'latest.cost.attendance.academic_year',
59
+ 'latest.aid.median_debt.completers.overall',
60
+ 'latest.aid.pell_grant_rate',
61
+ 'latest.aid.federal_loan_rate',
62
+ 'latest.repayment.3_yr_repayment.overall',
63
+ 'latest.completion.rate_suppressed.overall',
64
+ 'latest.earnings.6_yrs_after_entry.median',
65
+ 'latest.earnings.6_yrs_after_entry.percentile25',
66
+ 'latest.earnings.6_yrs_after_entry.percentile75',
67
+ 'latest.earnings.8_yrs_after_entry.median_earnings',
68
+ 'latest.earnings.10_yrs_after_entry.median',
69
+ 'latest.earnings.10_yrs_after_entry.percentile25',
70
+ 'latest.earnings.10_yrs_after_entry.percentile75',
71
+ ].join(',');
72
+ /** Default fields for earnings time series */
73
+ const EARNINGS_DEFAULT_FIELDS = [
74
+ 'id',
75
+ 'school.name',
76
+ 'latest.earnings.6_yrs_after_entry.median',
77
+ 'latest.earnings.6_yrs_after_entry.percentile25',
78
+ 'latest.earnings.6_yrs_after_entry.percentile75',
79
+ 'latest.earnings.8_yrs_after_entry.median_earnings',
80
+ 'latest.earnings.10_yrs_after_entry.median',
81
+ 'latest.earnings.10_yrs_after_entry.percentile25',
82
+ 'latest.earnings.10_yrs_after_entry.percentile75',
83
+ 'latest.earnings.6_yrs_after_entry.female_students.median_earnings',
84
+ 'latest.earnings.6_yrs_after_entry.male_students.median_earnings',
85
+ ].join(',');
86
+ /** Fields for program-level data */
87
+ const PROGRAMS_DEFAULT_FIELDS = ['id', 'school.name', 'latest.programs.cip_4_digit'].join(',');
88
+ export class ScorecardService {
89
+ apiKey;
90
+ constructor(_config, _storage) {
91
+ this.apiKey = getServerConfig().apiKey;
92
+ }
93
+ /** Build URL with query parameters */
94
+ buildUrl(params) {
95
+ const url = new URL(BASE_URL);
96
+ url.searchParams.set('api_key', this.apiKey);
97
+ for (const [key, value] of Object.entries(params)) {
98
+ if (value !== undefined && value !== '') {
99
+ url.searchParams.set(key, String(value));
100
+ }
101
+ }
102
+ return url.toString();
103
+ }
104
+ /** Fetch from the API with retry and error classification */
105
+ fetchApi(params, ctx) {
106
+ const url = this.buildUrl(params);
107
+ ctx.log.debug('Fetching Scorecard API', { path: url.replace(/api_key=[^&]+/, 'api_key=***') });
108
+ return withRetry(async () => {
109
+ const controller = new AbortController();
110
+ const timer = setTimeout(() => controller.abort(), 30_000);
111
+ const signal = ctx.signal
112
+ ? AbortSignal.any([ctx.signal, controller.signal])
113
+ : controller.signal;
114
+ let response;
115
+ try {
116
+ response = await fetch(url, { signal });
117
+ }
118
+ finally {
119
+ clearTimeout(timer);
120
+ }
121
+ if (!response.ok) {
122
+ const status = response.status;
123
+ if (status === 429)
124
+ throw serviceUnavailable(`Scorecard API rate limit exceeded (HTTP 429).`);
125
+ if (status === 403 || status === 401)
126
+ throw serviceUnavailable(`Scorecard API key rejected (HTTP ${status}) — verify SCORECARD_API_KEY.`);
127
+ if (status >= 500)
128
+ throw serviceUnavailable(`Scorecard API unavailable (HTTP ${status}).`);
129
+ throw serviceUnavailable(`Scorecard API returned HTTP ${status}.`);
130
+ }
131
+ const text = await response.text();
132
+ // Detect HTML error pages
133
+ if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
134
+ throw serviceUnavailable('Scorecard API returned HTML instead of JSON — likely rate-limited or unavailable.');
135
+ }
136
+ let body;
137
+ try {
138
+ body = JSON.parse(text);
139
+ }
140
+ catch {
141
+ throw serviceUnavailable('Scorecard API returned non-JSON response.', {
142
+ body: text.slice(0, 200),
143
+ });
144
+ }
145
+ const data = body;
146
+ // Check for API-level errors
147
+ if (data.error || (Array.isArray(data.errors) && data.errors.length > 0)) {
148
+ const apiErr = data;
149
+ const msg = apiErr.error?.message ??
150
+ apiErr.errors?.[0]?.message ??
151
+ 'Scorecard API returned an error.';
152
+ const code = apiErr.error?.code ?? apiErr.errors?.[0]?.error;
153
+ if (code === 'API_KEY_MISSING' || code === 'API_KEY_INVALID') {
154
+ throw serviceUnavailable(`Scorecard API key error: ${msg} — verify SCORECARD_API_KEY is valid.`);
155
+ }
156
+ throw serviceUnavailable(`Scorecard API error: ${msg}`, { code });
157
+ }
158
+ if (!data.results || !data.metadata) {
159
+ throw serviceUnavailable('Scorecard API returned unexpected response shape.', {
160
+ keys: Object.keys(data),
161
+ });
162
+ }
163
+ return data;
164
+ }, {
165
+ operation: 'ScorecardService.fetchApi',
166
+ baseDelayMs: 1000,
167
+ signal: ctx.signal,
168
+ });
169
+ }
170
+ /** Search schools with filter params */
171
+ searchSchools(options, ctx) {
172
+ const params = {
173
+ fields: options.fields ?? SEARCH_DEFAULT_FIELDS,
174
+ per_page: options.perPage ?? 20,
175
+ page: options.page ?? 0,
176
+ };
177
+ if (options.name)
178
+ params['school.name'] = options.name;
179
+ if (options.state)
180
+ params['school.state'] = options.state;
181
+ if (options.ownership != null)
182
+ params['school.ownership'] = options.ownership;
183
+ if (options.degreeLevel != null)
184
+ params['school.degrees_awarded.predominant'] = options.degreeLevel;
185
+ if (options.sizeRange) {
186
+ const [min, max] = options.sizeRange;
187
+ params['latest.student.size__range'] = `${min}..${max}`;
188
+ }
189
+ if (options.acceptanceRateRange) {
190
+ const [min, max] = options.acceptanceRateRange;
191
+ params['latest.admissions.admission_rate.overall__range'] = `${min}..${max}`;
192
+ }
193
+ if (options.zip)
194
+ params.zip = options.zip;
195
+ if (options.distance)
196
+ params.distance = options.distance;
197
+ if (options.cipCode)
198
+ params['latest.programs.cip_4_digit.code'] = options.cipCode.replace('.', '');
199
+ if (options.sort)
200
+ params.sort = options.sort;
201
+ if (options.extraParams) {
202
+ for (const [k, v] of Object.entries(options.extraParams)) {
203
+ params[k] = v;
204
+ }
205
+ }
206
+ return this.fetchApi(params, ctx);
207
+ }
208
+ /** Fetch one or more school profiles by ID */
209
+ getSchoolProfiles(ids, fields, ctx) {
210
+ if (ids.length === 0)
211
+ throw notFound('No school IDs provided.');
212
+ const params = {
213
+ id: ids.join(','),
214
+ fields: fields ?? PROFILE_DEFAULT_FIELDS,
215
+ per_page: Math.min(ids.length, 100),
216
+ };
217
+ return this.fetchApi(params, ctx);
218
+ }
219
+ /** Fetch program data for a school */
220
+ getSchoolPrograms(id, cipCode, _minEarnings, _credentialLevel, ctx) {
221
+ const params = {
222
+ id: String(id),
223
+ fields: PROGRAMS_DEFAULT_FIELDS,
224
+ per_page: 1,
225
+ };
226
+ if (cipCode) {
227
+ params['latest.programs.cip_4_digit.code'] = cipCode.replace('.', '');
228
+ }
229
+ return this.fetchApi(params, ctx);
230
+ }
231
+ /** Fetch earnings time series for a school */
232
+ getSchoolEarnings(id, years, ctx) {
233
+ const yearFields = years.length > 0
234
+ ? years
235
+ .flatMap((y) => [
236
+ `${y}.earnings.6_yrs_after_entry.median`,
237
+ `${y}.earnings.10_yrs_after_entry.median`,
238
+ ])
239
+ .join(',')
240
+ : '';
241
+ const params = {
242
+ id: String(id),
243
+ fields: yearFields ? `${EARNINGS_DEFAULT_FIELDS},${yearFields}` : EARNINGS_DEFAULT_FIELDS,
244
+ per_page: 1,
245
+ };
246
+ return this.fetchApi(params, ctx);
247
+ }
248
+ /** Search programs across schools */
249
+ searchPrograms(options, ctx) {
250
+ const params = {
251
+ fields: [
252
+ 'id',
253
+ 'school.name',
254
+ 'school.state',
255
+ 'school.ownership',
256
+ 'latest.cost.avg_net_price.overall',
257
+ 'latest.programs.cip_4_digit',
258
+ ].join(','),
259
+ per_page: options.perPage ?? 20,
260
+ page: options.page ?? 0,
261
+ };
262
+ if (options.cipCode)
263
+ params['latest.programs.cip_4_digit.code'] = options.cipCode.replace('.', '');
264
+ if (options.state)
265
+ params['school.state'] = options.state;
266
+ if (options.ownership != null)
267
+ params['school.ownership'] = options.ownership;
268
+ if (options.maxNetPrice != null)
269
+ params['latest.cost.avg_net_price.overall__range'] = `..${options.maxNetPrice}`;
270
+ if (options.minEarnings != null) {
271
+ params['latest.programs.cip_4_digit.earnings.highest.1_yr.overall_median_earnings__range'] =
272
+ `${options.minEarnings}..`;
273
+ }
274
+ if (options.maxDebt != null) {
275
+ params['latest.programs.cip_4_digit.debt.median_debt__range'] = `..${options.maxDebt}`;
276
+ }
277
+ return this.fetchApi(params, ctx);
278
+ }
279
+ /** Fetch fields for value analysis (cost + earnings in parallel) */
280
+ getValueAnalysisData(id, ctx) {
281
+ const costFields = [
282
+ 'id',
283
+ 'school.name',
284
+ 'school.carnegie_basic',
285
+ 'school.ownership',
286
+ 'latest.cost.tuition.in_state',
287
+ 'latest.cost.tuition.out_of_state',
288
+ 'latest.cost.avg_net_price.overall',
289
+ 'latest.cost.avg_net_price.by_income.0-30000',
290
+ 'latest.cost.avg_net_price.by_income.30001-48000',
291
+ 'latest.cost.avg_net_price.by_income.48001-75000',
292
+ 'latest.cost.avg_net_price.by_income.75001-110000',
293
+ 'latest.cost.avg_net_price.by_income.110001-plus',
294
+ 'latest.aid.median_debt.completers.overall',
295
+ 'latest.repayment.3_yr_repayment.overall',
296
+ 'latest.completion.rate_suppressed.overall',
297
+ ].join(',');
298
+ const earningsFields = [
299
+ 'id',
300
+ 'latest.earnings.6_yrs_after_entry.median',
301
+ 'latest.earnings.6_yrs_after_entry.percentile25',
302
+ 'latest.earnings.6_yrs_after_entry.percentile75',
303
+ 'latest.earnings.8_yrs_after_entry.median_earnings',
304
+ 'latest.earnings.10_yrs_after_entry.median',
305
+ ].join(',');
306
+ return Promise.all([
307
+ this.fetchApi({ id: String(id), fields: costFields, per_page: 1 }, ctx),
308
+ this.fetchApi({ id: String(id), fields: earningsFields, per_page: 1 }, ctx),
309
+ ]);
310
+ }
311
+ /** Fetch comparison data for multiple schools on a specific topic */
312
+ getComparisonData(ids, topic, ctx) {
313
+ const topicFields = {
314
+ costs: [
315
+ 'id',
316
+ 'school.name',
317
+ 'latest.cost.tuition.in_state',
318
+ 'latest.cost.tuition.out_of_state',
319
+ 'latest.cost.avg_net_price.overall',
320
+ 'latest.cost.avg_net_price.by_income.0-30000',
321
+ 'latest.cost.avg_net_price.by_income.30001-48000',
322
+ 'latest.cost.avg_net_price.by_income.48001-75000',
323
+ 'latest.cost.avg_net_price.by_income.75001-110000',
324
+ 'latest.cost.avg_net_price.by_income.110001-plus',
325
+ 'latest.aid.median_debt.completers.overall',
326
+ ].join(','),
327
+ admissions: [
328
+ 'id',
329
+ 'school.name',
330
+ 'latest.admissions.admission_rate.overall',
331
+ 'latest.admissions.sat_scores.average.overall',
332
+ 'latest.admissions.sat_scores.25th_percentile.math',
333
+ 'latest.admissions.sat_scores.75th_percentile.math',
334
+ 'latest.admissions.act_scores.25th_percentile.cumulative',
335
+ 'latest.admissions.act_scores.75th_percentile.cumulative',
336
+ 'latest.student.size',
337
+ ].join(','),
338
+ outcomes: [
339
+ 'id',
340
+ 'school.name',
341
+ 'latest.completion.rate_suppressed.overall',
342
+ 'latest.earnings.6_yrs_after_entry.median',
343
+ 'latest.earnings.10_yrs_after_entry.median',
344
+ 'latest.repayment.3_yr_repayment.overall',
345
+ 'latest.aid.median_debt.completers.overall',
346
+ ].join(','),
347
+ aid: [
348
+ 'id',
349
+ 'school.name',
350
+ 'latest.aid.pell_grant_rate',
351
+ 'latest.aid.federal_loan_rate',
352
+ 'latest.aid.median_debt.completers.overall',
353
+ 'latest.repayment.3_yr_repayment.overall',
354
+ 'latest.cost.avg_net_price.overall',
355
+ ].join(','),
356
+ };
357
+ const params = {
358
+ id: ids.join(','),
359
+ fields: topicFields[topic],
360
+ per_page: ids.length,
361
+ };
362
+ return this.fetchApi(params, ctx);
363
+ }
364
+ }
365
+ // --- Init/accessor pattern ---
366
+ let _service;
367
+ export function initScorecardService(config, storage) {
368
+ _service = new ScorecardService(config, storage);
369
+ }
370
+ export function getScorecardService() {
371
+ if (!_service) {
372
+ throw new Error('ScorecardService not initialized — call initScorecardService() in setup()');
373
+ }
374
+ return _service;
375
+ }
376
+ //# sourceMappingURL=scorecard-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scorecard-service.js","sourceRoot":"","sources":["../../../src/services/scorecard/scorecard-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @fileoverview Domain types for College Scorecard API responses.
3
+ * @module services/scorecard/types
4
+ */
5
+ /** Nested program object returned under `latest.programs.cip_4_digit` */
6
+ export interface RawProgram {
7
+ code?: string;
8
+ counts?: {
9
+ ipeds_enrollment?: number | null;
10
+ };
11
+ credential?: {
12
+ level?: number | null;
13
+ title?: string | null;
14
+ };
15
+ debt?: {
16
+ median_debt?: number | null;
17
+ };
18
+ earnings?: {
19
+ highest?: {
20
+ '1_yr'?: {
21
+ overall_median_earnings?: number | null;
22
+ overall_count_titleiv?: number | null;
23
+ };
24
+ };
25
+ };
26
+ title?: string;
27
+ }
28
+ /** Raw school record from the Scorecard API (fields vary by query). */
29
+ export interface RawSchoolRecord {
30
+ id?: number;
31
+ 'latest.admissions.act_scores.25th_percentile.cumulative'?: number | null;
32
+ 'latest.admissions.act_scores.75th_percentile.cumulative'?: number | null;
33
+ 'latest.admissions.admission_rate.overall'?: number | null;
34
+ 'latest.admissions.sat_scores.25th_percentile.critical_reading'?: number | null;
35
+ 'latest.admissions.sat_scores.25th_percentile.math'?: number | null;
36
+ 'latest.admissions.sat_scores.75th_percentile.critical_reading'?: number | null;
37
+ 'latest.admissions.sat_scores.75th_percentile.math'?: number | null;
38
+ 'latest.admissions.sat_scores.average.overall'?: number | null;
39
+ 'latest.aid.federal_loan_rate'?: number | null;
40
+ 'latest.aid.median_debt.completers.overall'?: number | null;
41
+ 'latest.aid.pell_grant_rate'?: number | null;
42
+ 'latest.completion.rate_suppressed.overall'?: number | null;
43
+ 'latest.cost.attendance.academic_year'?: number | null;
44
+ 'latest.cost.avg_net_price.by_income.0-30000'?: number | null;
45
+ 'latest.cost.avg_net_price.by_income.30001-48000'?: number | null;
46
+ 'latest.cost.avg_net_price.by_income.48001-75000'?: number | null;
47
+ 'latest.cost.avg_net_price.by_income.75001-110000'?: number | null;
48
+ 'latest.cost.avg_net_price.by_income.110001-plus'?: number | null;
49
+ 'latest.cost.avg_net_price.overall'?: number | null;
50
+ 'latest.cost.tuition.in_state'?: number | null;
51
+ 'latest.cost.tuition.out_of_state'?: number | null;
52
+ 'latest.earnings.6_yrs_after_entry.female_students.median_earnings'?: number | null;
53
+ 'latest.earnings.6_yrs_after_entry.male_students.median_earnings'?: number | null;
54
+ 'latest.earnings.6_yrs_after_entry.median'?: number | null;
55
+ 'latest.earnings.6_yrs_after_entry.percentile25'?: number | null;
56
+ 'latest.earnings.6_yrs_after_entry.percentile75'?: number | null;
57
+ 'latest.earnings.8_yrs_after_entry.median_earnings'?: number | null;
58
+ 'latest.earnings.10_yrs_after_entry.median'?: number | null;
59
+ 'latest.earnings.10_yrs_after_entry.percentile25'?: number | null;
60
+ 'latest.earnings.10_yrs_after_entry.percentile75'?: number | null;
61
+ 'latest.programs.cip_4_digit'?: RawProgram[];
62
+ 'latest.repayment.3_yr_repayment.overall'?: number | null;
63
+ 'latest.student.size'?: number | null;
64
+ 'school.carnegie_basic'?: number | null;
65
+ 'school.city'?: string;
66
+ 'school.degrees_awarded.predominant'?: number | null;
67
+ 'school.hbcu'?: number | null;
68
+ 'school.institutional_characteristics.level'?: number | null;
69
+ 'school.locale'?: number | null;
70
+ 'school.men_only'?: number | null;
71
+ 'school.name'?: string;
72
+ 'school.ownership'?: number | null;
73
+ 'school.school_url'?: string;
74
+ 'school.state'?: string;
75
+ 'school.women_only'?: number | null;
76
+ 'school.zip'?: string;
77
+ [key: string]: unknown;
78
+ }
79
+ /** Raw API response envelope */
80
+ export interface ScorecardApiResponse {
81
+ metadata: {
82
+ total: number;
83
+ page: number;
84
+ per_page: number;
85
+ };
86
+ results: RawSchoolRecord[];
87
+ }
88
+ /** Error shape returned by the Scorecard API */
89
+ export interface ScorecardApiError {
90
+ error?: {
91
+ code?: string;
92
+ message?: string;
93
+ };
94
+ errors?: Array<{
95
+ error?: string;
96
+ input?: string;
97
+ message?: string;
98
+ }>;
99
+ }
100
+ /** Options for a search query */
101
+ export interface ScorecardSearchOptions {
102
+ /** Acceptance rate range [min, max] 0-1 */
103
+ acceptanceRateRange?: [number, number];
104
+ /** CIP code filter */
105
+ cipCode?: string;
106
+ /** Predominant degree level: 0-4 */
107
+ degreeLevel?: number;
108
+ /** Distance from zip (e.g. "50mi") */
109
+ distance?: string;
110
+ /** Additional query params */
111
+ extraParams?: Record<string, string | number>;
112
+ /** Custom field selection (comma-separated) */
113
+ fields?: string;
114
+ /** School unit ID(s) for batch lookup */
115
+ id?: string | number | Array<string | number>;
116
+ /** School name full-text filter */
117
+ name?: string;
118
+ /** Ownership type: 1=public, 2=private nonprofit, 3=for-profit */
119
+ ownership?: number;
120
+ page?: number;
121
+ perPage?: number;
122
+ /** Enrollment size range [min, max] */
123
+ sizeRange?: [number, number];
124
+ /** Sort expression (e.g. "latest.cost.tuition.in_state:asc") */
125
+ sort?: string;
126
+ /** Two-letter state code */
127
+ state?: string;
128
+ /** US zip code for geographic filter */
129
+ zip?: string;
130
+ }
131
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/scorecard/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Domain types for College Scorecard API responses.
3
+ * @module services/scorecard/types
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/scorecard/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@cyanheads/college-scorecard-mcp-server",
3
+ "version": "0.1.1",
4
+ "description": "Search, compare, and analyze U.S. college data — costs, earnings, programs, and outcomes — via MCP. STDIO or Streamable HTTP.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "college-scorecard-mcp-server": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "changelog/",
13
+ "dist/",
14
+ "README.md",
15
+ "LICENSE",
16
+ "CLAUDE.md",
17
+ "Dockerfile",
18
+ "server.json"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsx scripts/build.ts",
22
+ "rebuild": "tsx scripts/clean.ts && tsx scripts/build.ts",
23
+ "clean": "tsx scripts/clean.ts",
24
+ "devcheck": "tsx scripts/devcheck.ts",
25
+ "audit:refresh": "rm -f bun.lock && bun install && bun audit",
26
+ "tree": "tsx scripts/tree.ts",
27
+ "list-skills": "tsx scripts/list-skills.ts",
28
+ "format": "biome check --write --unsafe .",
29
+ "lint:mcp": "tsx scripts/lint-mcp.ts",
30
+ "lint:packaging": "tsx scripts/lint-packaging.ts",
31
+ "bundle": "npm run build && npx -y @anthropic-ai/mcpb pack . dist/college-scorecard-mcp-server.mcpb",
32
+ "changelog:build": "tsx scripts/build-changelog.ts",
33
+ "changelog:check": "tsx scripts/build-changelog.ts --check",
34
+ "test": "vitest run",
35
+ "start": "node dist/index.js",
36
+ "start:stdio": "MCP_TRANSPORT_TYPE=stdio node dist/index.js",
37
+ "start:http": "MCP_TRANSPORT_TYPE=http node dist/index.js"
38
+ },
39
+ "keywords": [
40
+ "mcp",
41
+ "mcp-server",
42
+ "model-context-protocol",
43
+ "college-scorecard",
44
+ "higher-education",
45
+ "department-of-education",
46
+ "college-search",
47
+ "university-data",
48
+ "financial-aid",
49
+ "student-outcomes",
50
+ "post-graduation-earnings",
51
+ "college-comparison"
52
+ ],
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/cyanheads/college-scorecard-mcp-server.git"
56
+ },
57
+ "license": "Apache-2.0",
58
+ "engines": {
59
+ "bun": ">=1.3.0",
60
+ "node": ">=24.0.0"
61
+ },
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "dependencies": {
66
+ "@cyanheads/mcp-ts-core": "^0.9.9",
67
+ "pino-pretty": "^13.1.3",
68
+ "zod": "^4.4.3"
69
+ },
70
+ "devDependencies": {
71
+ "@biomejs/biome": "^2.4.15",
72
+ "@types/node": "^25.9.1",
73
+ "depcheck": "^1.4.7",
74
+ "ignore": "^7.0.5",
75
+ "tsc-alias": "^1.8.17",
76
+ "tsx": "^4.22.3",
77
+ "typescript": "^6.0.3",
78
+ "vitest": "^4.1.7"
79
+ }
80
+ }