@cyanheads/college-scorecard-mcp-server 0.2.0 → 0.4.0
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.
- package/AGENTS.md +12 -6
- package/CLAUDE.md +12 -6
- package/Dockerfile +6 -3
- package/README.md +52 -24
- package/changelog/0.3.x/0.3.0.md +31 -0
- package/changelog/0.4.x/0.4.0.md +31 -0
- package/dist/data/cip-codes.d.ts +6 -1
- package/dist/data/cip-codes.d.ts.map +1 -1
- package/dist/data/cip-codes.js +561 -447
- package/dist/data/cip-codes.js.map +1 -1
- package/dist/data/earnings-context.d.ts +33 -0
- package/dist/data/earnings-context.d.ts.map +1 -0
- package/dist/data/earnings-context.js +148 -0
- package/dist/data/earnings-context.js.map +1 -0
- package/dist/data/field-catalog.d.ts.map +1 -1
- package/dist/data/field-catalog.js +8 -22
- package/dist/data/field-catalog.js.map +1 -1
- package/dist/mcp-server/prompts/definitions/compare.prompt.d.ts.map +1 -1
- package/dist/mcp-server/prompts/definitions/compare.prompt.js +7 -5
- package/dist/mcp-server/prompts/definitions/compare.prompt.js.map +1 -1
- package/dist/mcp-server/resources/definitions/programs.resource.d.ts +73 -1
- package/dist/mcp-server/resources/definitions/programs.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/programs.resource.js +89 -3
- package/dist/mcp-server/resources/definitions/programs.resource.js.map +1 -1
- package/dist/mcp-server/resources/definitions/school.resource.d.ts +73 -1
- package/dist/mcp-server/resources/definitions/school.resource.d.ts.map +1 -1
- package/dist/mcp-server/resources/definitions/school.resource.js +89 -3
- package/dist/mcp-server/resources/definitions/school.resource.js.map +1 -1
- package/dist/mcp-server/tools/definitions/compare-schools.tool.d.ts +67 -2
- package/dist/mcp-server/tools/definitions/compare-schools.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/compare-schools.tool.js +101 -40
- package/dist/mcp-server/tools/definitions/compare-schools.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-earnings.tool.d.ts +85 -3
- package/dist/mcp-server/tools/definitions/get-earnings.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-earnings.tool.js +162 -51
- package/dist/mcp-server/tools/definitions/get-earnings.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-programs.tool.d.ts +68 -6
- package/dist/mcp-server/tools/definitions/get-programs.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-programs.tool.js +106 -31
- package/dist/mcp-server/tools/definitions/get-programs.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-school.tool.d.ts +67 -3
- package/dist/mcp-server/tools/definitions/get-school.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-school.tool.js +327 -177
- package/dist/mcp-server/tools/definitions/get-school.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/list-fields.tool.d.ts +7 -7
- package/dist/mcp-server/tools/definitions/list-fields.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/list-fields.tool.js +28 -23
- package/dist/mcp-server/tools/definitions/list-fields.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/lookup-cip.tool.d.ts +7 -7
- package/dist/mcp-server/tools/definitions/lookup-cip.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/lookup-cip.tool.js +33 -22
- package/dist/mcp-server/tools/definitions/lookup-cip.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/search-programs.tool.d.ts +71 -1
- package/dist/mcp-server/tools/definitions/search-programs.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-programs.tool.js +132 -15
- package/dist/mcp-server/tools/definitions/search-programs.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/search-schools.tool.d.ts +62 -1
- package/dist/mcp-server/tools/definitions/search-schools.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-schools.tool.js +107 -9
- package/dist/mcp-server/tools/definitions/search-schools.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/value-analysis.tool.d.ts +68 -1
- package/dist/mcp-server/tools/definitions/value-analysis.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/value-analysis.tool.js +105 -13
- package/dist/mcp-server/tools/definitions/value-analysis.tool.js.map +1 -1
- package/dist/services/scorecard/input-normalization.d.ts +21 -0
- package/dist/services/scorecard/input-normalization.d.ts.map +1 -0
- package/dist/services/scorecard/input-normalization.js +92 -0
- package/dist/services/scorecard/input-normalization.js.map +1 -0
- package/dist/services/scorecard/metric-availability.d.ts +17 -0
- package/dist/services/scorecard/metric-availability.d.ts.map +1 -0
- package/dist/services/scorecard/metric-availability.js +19 -0
- package/dist/services/scorecard/metric-availability.js.map +1 -0
- package/dist/services/scorecard/scorecard-service.d.ts +6 -4
- package/dist/services/scorecard/scorecard-service.d.ts.map +1 -1
- package/dist/services/scorecard/scorecard-service.js +112 -51
- package/dist/services/scorecard/scorecard-service.js.map +1 -1
- package/dist/services/scorecard/types.d.ts +16 -16
- package/dist/services/scorecard/types.d.ts.map +1 -1
- package/package.json +10 -10
- package/server.json +21 -23
package/AGENTS.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** college-scorecard-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/server` ^2.1
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.3.1
|
|
8
8
|
**Zod:** ^4.6.5
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -33,7 +33,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
33
33
|
## Core Rules
|
|
34
34
|
|
|
35
35
|
- **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `validationError()`, etc.) when the error code matters.
|
|
36
|
-
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
36
|
+
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
37
37
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
38
38
|
- **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler.
|
|
39
39
|
- **Secrets in env vars only** — never hardcoded.
|
|
@@ -179,6 +179,12 @@ await createApp({
|
|
|
179
179
|
|
|
180
180
|
This server declares `sessionMode: 'stateless'` in `src/index.ts`: no tool calls `ctx.requestInput`, so no request depends on a live session.
|
|
181
181
|
|
|
182
|
+
### Scorecard metric semantics
|
|
183
|
+
|
|
184
|
+
Institution earnings cover federally aided undergraduate entrants working and not enrolled, regardless of completion. Earnings `years` is the published API data-file start-year domain 1996–2025, not an entry-year selector. `src/data/earnings-context.ts` holds official per-metric cohort/measurement/dollar provenance; refresh it from the dictionary when coverage changes, never infer vintage by arithmetic or sample equality.
|
|
185
|
+
|
|
186
|
+
`readMetric` distinguishes numbers (including zero), unknown-cause null/absence, and explicit `PS` / `PrivacySuppressed` markers. Suppression flags/counts require the latter; unexpected values are provider contract failures. CIP lookup remains a curated set of current NCES four-digit groups, with exact group/family titles and verified descendant aliases. Program search applies CIP × credential together upstream before school pagination; totals remain school-level.
|
|
187
|
+
|
|
182
188
|
---
|
|
183
189
|
|
|
184
190
|
## Context
|
|
@@ -360,7 +366,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
360
366
|
|
|
361
367
|
## Bundling
|
|
362
368
|
|
|
363
|
-
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
369
|
+
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
364
370
|
|
|
365
371
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`.
|
|
366
372
|
|
|
@@ -397,7 +403,7 @@ security: false # optional — true ONLY for a source
|
|
|
397
403
|
|
|
398
404
|
## Publishing
|
|
399
405
|
|
|
400
|
-
**Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the
|
|
406
|
+
**Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the release digest: theme line, `## Changes`, `## Gates`, changelog link last); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. A caller's brief may run a given release as `gated` instead — a `release-pr-review` pass on the open PR before `release-and-publish`. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history.
|
|
401
407
|
|
|
402
408
|
---
|
|
403
409
|
|
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** college-scorecard-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/server` ^2.1
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.3.1
|
|
8
8
|
**Zod:** ^4.6.5
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -33,7 +33,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
33
33
|
## Core Rules
|
|
34
34
|
|
|
35
35
|
- **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `validationError()`, etc.) when the error code matters.
|
|
36
|
-
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
36
|
+
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
37
37
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
38
38
|
- **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler.
|
|
39
39
|
- **Secrets in env vars only** — never hardcoded.
|
|
@@ -179,6 +179,12 @@ await createApp({
|
|
|
179
179
|
|
|
180
180
|
This server declares `sessionMode: 'stateless'` in `src/index.ts`: no tool calls `ctx.requestInput`, so no request depends on a live session.
|
|
181
181
|
|
|
182
|
+
### Scorecard metric semantics
|
|
183
|
+
|
|
184
|
+
Institution earnings cover federally aided undergraduate entrants working and not enrolled, regardless of completion. Earnings `years` is the published API data-file start-year domain 1996–2025, not an entry-year selector. `src/data/earnings-context.ts` holds official per-metric cohort/measurement/dollar provenance; refresh it from the dictionary when coverage changes, never infer vintage by arithmetic or sample equality.
|
|
185
|
+
|
|
186
|
+
`readMetric` distinguishes numbers (including zero), unknown-cause null/absence, and explicit `PS` / `PrivacySuppressed` markers. Suppression flags/counts require the latter; unexpected values are provider contract failures. CIP lookup remains a curated set of current NCES four-digit groups, with exact group/family titles and verified descendant aliases. Program search applies CIP × credential together upstream before school pagination; totals remain school-level.
|
|
187
|
+
|
|
182
188
|
---
|
|
183
189
|
|
|
184
190
|
## Context
|
|
@@ -360,7 +366,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
360
366
|
|
|
361
367
|
## Bundling
|
|
362
368
|
|
|
363
|
-
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
369
|
+
`npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
|
|
364
370
|
|
|
365
371
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`.
|
|
366
372
|
|
|
@@ -397,7 +403,7 @@ security: false # optional — true ONLY for a source
|
|
|
397
403
|
|
|
398
404
|
## Publishing
|
|
399
405
|
|
|
400
|
-
**Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the
|
|
406
|
+
**Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the release digest: theme line, `## Changes`, `## Gates`, changelog link last); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. A caller's brief may run a given release as `gated` instead — a `release-pr-review` pass on the open PR before `release-and-publish`. **Never merge through the GitHub UI or `gh pr merge`**: squash and rebase-merge are disabled in the repo settings because both rewrite the stack (rebase-merge also strips the SSH signatures), and a merge commit breaks the linear history.
|
|
401
407
|
|
|
402
408
|
---
|
|
403
409
|
|
package/Dockerfile
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# output. A stage that compiles a native addon needs the target-arch toolchain
|
|
15
15
|
# and cannot cross-compile this way — drop the flag there.
|
|
16
16
|
# ==============================================================================
|
|
17
|
-
FROM --platform=$BUILDPLATFORM oven/bun:1.4.
|
|
17
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.3 AS build
|
|
18
18
|
|
|
19
19
|
WORKDIR /usr/src/app
|
|
20
20
|
|
|
@@ -41,7 +41,7 @@ RUN bun run build
|
|
|
41
41
|
# Run the scanner and OTel installer natively, cross-installing production
|
|
42
42
|
# dependencies for the target architecture. Only node_modules leaves this stage.
|
|
43
43
|
# ==============================================================================
|
|
44
|
-
FROM --platform=$BUILDPLATFORM oven/bun:1.4.
|
|
44
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.3 AS deps
|
|
45
45
|
|
|
46
46
|
WORKDIR /usr/src/app
|
|
47
47
|
|
|
@@ -78,6 +78,9 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
|
78
78
|
bun scripts/install-otel.ts --os="$TARGETOS" --cpu="$(cat .bun-cpu)"; \
|
|
79
79
|
fi
|
|
80
80
|
|
|
81
|
+
COPY scripts/prune-musl-packages.ts ./scripts/
|
|
82
|
+
RUN bun scripts/prune-musl-packages.ts
|
|
83
|
+
|
|
81
84
|
# The scanner is only needed during installation.
|
|
82
85
|
RUN rm -rf node_modules/@socketsecurity/bun-security-scanner
|
|
83
86
|
|
|
@@ -87,7 +90,7 @@ RUN rm -rf node_modules/@socketsecurity/bun-security-scanner
|
|
|
87
90
|
#
|
|
88
91
|
# Runtime-only stage: Bun runs on the target architecture at container start.
|
|
89
92
|
# ==============================================================================
|
|
90
|
-
FROM oven/bun:1.4.
|
|
93
|
+
FROM oven/bun:1.4.3-slim AS production
|
|
91
94
|
|
|
92
95
|
WORKDIR /usr/src/app
|
|
93
96
|
ENV NODE_ENV=production
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/college-scorecard-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/college-scorecard-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -19,11 +19,17 @@
|
|
|
19
19
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
|
+
<div align="center">
|
|
23
|
+
|
|
24
|
+
**Public Hosted Server:** [https://college-scorecard.caseyjhand.com/mcp](https://college-scorecard.caseyjhand.com/mcp)
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
22
28
|
---
|
|
23
29
|
|
|
24
30
|
## Overview
|
|
25
31
|
|
|
26
|
-
U.S. college data from the Department of Education College Scorecard API — costs, earnings, programs, and outcomes across roughly 6,500 Title IV institutions. Search and compare schools, look up program-level earnings by field of study, and compute ROI metrics like debt-to-earnings ratio from any MCP client. Runs as a stdio process
|
|
32
|
+
U.S. college data from the Department of Education College Scorecard API — costs, earnings, programs, and outcomes across roughly 6,500 Title IV institutions. Search and compare schools, look up program-level earnings by field of study, and compute ROI metrics like debt-to-earnings ratio from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
|
|
27
33
|
|
|
28
34
|
### Tools
|
|
29
35
|
|
|
@@ -31,12 +37,12 @@ U.S. college data from the Department of Education College Scorecard API — cos
|
|
|
31
37
|
|:---|:---|
|
|
32
38
|
| `scorecard_search_schools` | Search institutions by name, location, type, size, acceptance rate, and single-sex flags; sort by supported API fields. Returns core identity and cost metrics. |
|
|
33
39
|
| `scorecard_get_school` | Full institutional profiles — costs, admissions, outcomes, aid, demographics, single-sex flags, and completion rates. |
|
|
34
|
-
| `scorecard_compare_schools` | Normalized side-by-side comparison of 2–5 schools on a named topic. Returns
|
|
40
|
+
| `scorecard_compare_schools` | Normalized side-by-side comparison of 2–5 schools on a named topic. Returns metric values, ordinal ranks, and a comparison summary. |
|
|
35
41
|
| `scorecard_get_programs` | Field-of-study programs at one school: median 1-year earnings, cumulative Stafford/Grad PLUS debt, and IPEDS awards in the two pooled debt-cohort years. |
|
|
36
|
-
| `scorecard_search_programs` | Find programs by CIP
|
|
37
|
-
| `scorecard_get_earnings` |
|
|
42
|
+
| `scorecard_search_programs` | Find programs by CIP and credential or keyword, retain degree identity, and rank earnings within each fetched school page. |
|
|
43
|
+
| `scorecard_get_earnings` | Earnings of federally aided undergraduate entrants working and not enrolled, regardless of completion: 6/8/10-year medians, 6/10-year P25/P75, and non-male/male 6-year medians. |
|
|
38
44
|
| `scorecard_value_analysis` | Workflow tool: parallel-fetches cost, debt, repayment, and earnings data, then computes ROI metrics — debt-to-earnings ratio and net price to earnings ratio. |
|
|
39
|
-
| `scorecard_lookup_cip` | Search
|
|
45
|
+
| `scorecard_lookup_cip` | Search 186 curated NCES CIP 2020 four-digit groups by code, keyword, or verified descendant alias. Served offline. |
|
|
40
46
|
| `scorecard_list_fields` | Search the Scorecard field catalog by keyword. Returns matching field paths, descriptions, data types, and sort support. Use before passing custom `fields` parameters. |
|
|
41
47
|
|
|
42
48
|
### Resources
|
|
@@ -58,7 +64,7 @@ All resource data is also reachable via tools. Use `scorecard_search_schools` or
|
|
|
58
64
|
|
|
59
65
|
### `scorecard_search_schools` <sub>tool</sub>
|
|
60
66
|
|
|
61
|
-
- Search by name, state, ownership, degree level, size, acceptance rate, CIP code, or
|
|
67
|
+
- Search by name, state, ownership, degree level, size, acceptance rate, CIP code, or ZIP and distance; `per_page` is capped at 100 with zero-indexed `page`. State lists accept `WA,CA` and case variants. ZIP-only queries use the provider default radius; ZIP+4 and nonnegative decimal radii (bare miles, `mi`, or `km`) are supported. Reversed range bounds normalize to ascending order.
|
|
62
68
|
- Returns core identity and cost metrics for quick scanning.
|
|
63
69
|
- `sort` forwards a supported API expression such as `latest.cost.avg_net_price.overall:asc` (`:desc` reverses it). `men_only` and `women_only` accept true or false; omission includes unknown flags, while false selects only explicit zero values.
|
|
64
70
|
|
|
@@ -66,59 +72,62 @@ All resource data is also reachable via tools. Use `scorecard_search_schools` or
|
|
|
66
72
|
|
|
67
73
|
### `scorecard_get_school` <sub>tool</sub>
|
|
68
74
|
|
|
69
|
-
- Accepts a
|
|
70
|
-
-
|
|
75
|
+
- Accepts a positive safe integer school ID or an array of up to 1,000 elements. Base-10 strings accept whitespace, leading zeros, plus, decimal, and exponent forms when they resolve to a positive safe integer. IDs are deduplicated before the first 100 distinct IDs are fetched; `missing_ids` identifies processed IDs without records, and `unprocessed_ids` identifies unchecked excess.
|
|
76
|
+
- Default profiles cover costs, admissions, outcomes, financial aid, demographics, and completion rates. Custom `fields` returns real ID/name plus `selected_fields` containing requested JSON values, including null, zero, false, and nested arrays. Program leaf projections retain the provider's parent subtree under `latest.programs.cip_4_digit`, preserving sparse rows and array positions; `absent_fields` lists requested paths omitted from that response. Unrequested profile metrics are omitted.
|
|
77
|
+
- HBCU status reads `school.minority_serving.historically_black`; HBCU and single-sex flags preserve true/false when known and remain unknown when absent/null.
|
|
71
78
|
|
|
72
79
|
---
|
|
73
80
|
|
|
74
81
|
### `scorecard_compare_schools` <sub>tool</sub>
|
|
75
82
|
|
|
76
83
|
- Accepts 2–5 school unit IDs and one topic: `costs`, `admissions`, `outcomes`, or `aid`.
|
|
77
|
-
- Returns
|
|
84
|
+
- Returns metric values and competition ranks from one API call: equal values share a rank (1, 1, 3), unavailable values are unranked, and summaries name tied leaders. Each cell's `availability` distinguishes available, unavailable with unknown cause, and confirmed privacy suppression.
|
|
78
85
|
|
|
79
86
|
---
|
|
80
87
|
|
|
81
88
|
### `scorecard_get_programs` <sub>tool</sub>
|
|
82
89
|
|
|
83
90
|
- Accepts one school ID, with optional CIP code, `credential_level`, and minimum earnings filters.
|
|
84
|
-
-
|
|
91
|
+
- Existing schools with no reported or matching programs return a successful empty collection; a nonexistent school remains a lookup error. Dotted and undotted four-digit CIP codes are equivalent.
|
|
92
|
+
- Returns median earnings and the matching count of graduates working and not enrolled 1 year after their highest credential. `earnings_availability` is `available`, `unavailable`, or `privacy_suppressed`; zero is available, null/absence has unknown cause, and only explicit provider privacy markers set `suppressed`. `suppressed_count` and `unavailable_count` distinguish those populations.
|
|
85
93
|
- `median_debt` is completers' cumulative Stafford/Grad PLUS borrowing across attended institutions at the same academic level. `ipeds_awards_year1` and `ipeds_awards_year2` count awards in each year of the pooled debt cohort, not enrollment or unique students.
|
|
86
94
|
|
|
87
95
|
---
|
|
88
96
|
|
|
89
97
|
### `scorecard_search_programs` <sub>tool</sub>
|
|
90
98
|
|
|
91
|
-
- Search by CIP code or program name, with state, ownership, net price, earnings, and debt filters; zero-indexed `page` and `per_page` (up to 100) paginate schools, so returned program rows may exceed `per_page`.
|
|
92
|
-
- Returns school IDs and names alongside program metrics
|
|
99
|
+
- Search by CIP code or program name, with optional integer `credential_level`, state, ownership, net price, earnings, and debt filters; zero-indexed `page` and `per_page` (up to 100) paginate schools, so returned program rows may exceed `per_page`. CIP and credential selectors apply together upstream before pagination; credential codes are 1–8 and 99, and unknown integer selectors may return no matches.
|
|
100
|
+
- Returns school IDs and names alongside program metrics and provider `credential_level` / `credential_title`, retaining separate credentials and future numeric credential levels; missing identity fields stay absent. Available earnings sort first; availability states and counts have the same meaning as in `scorecard_get_programs`.
|
|
93
101
|
- `min_earnings` filters locally; totals and pagination remain upstream school counts before local filtering. Earnings/debt thresholds are inclusive and exclude unknown values. Debt and award fields have the same meanings as in `scorecard_get_programs`.
|
|
94
102
|
|
|
95
103
|
---
|
|
96
104
|
|
|
97
105
|
### `scorecard_get_earnings` <sub>tool</sub>
|
|
98
106
|
|
|
99
|
-
- Accepts one school ID and optional `years`
|
|
100
|
-
-
|
|
101
|
-
-
|
|
107
|
+
- Accepts one school ID and optional API data-file start `years` from 1996–2025. These are file vintages, not entry years; valid files without observations succeed. Omit `years` or pass `[]` for snapshot only.
|
|
108
|
+
- Institution earnings cover federally aided undergraduate entrants working and not enrolled, regardless of completion. Returns medians at 6/8/10 years after entry, 6/10-year P25/P75, and non-male/male 6-year medians.
|
|
109
|
+
- `current_availability` and `trend[].availability` classify each supported metric; aggregate `suppressed` requires every current metric to carry an explicit privacy marker. Null and omitted values do not prove suppression.
|
|
110
|
+
- `current_context` and `trend[].context` give per-metric `data_file_year`, verified academic `entry_cohorts`, calendar `measurement_years`, and inflation `dollar_year`. Metadata comes from the official cohort maps; unknown parts are omitted. Values retain the provider's dollar basis, so cross-vintage comparisons require checking it. Each requested file adds six- and ten-year medians without extra requests.
|
|
102
111
|
|
|
103
112
|
---
|
|
104
113
|
|
|
105
114
|
### `scorecard_value_analysis` <sub>tool</sub>
|
|
106
115
|
|
|
107
116
|
- Accepts one school ID; optional `family_income` selects the applicable net price bracket ($0–30k, $30k–48k, $48k–75k, $75k–110k, or $110k+).
|
|
108
|
-
- Returns
|
|
117
|
+
- Returns ratios alongside their source figures. `effective_net_price` discloses the price used, and `net_price_basis` is `income_bracket`, `overall`, or `unavailable`. A missing bracket preserves requested `family_income` / `applicable_income_bracket` and explains the established overall-price fallback in `data_notes`. Zero estimates remain valid; ratios require positive annual earnings.
|
|
109
118
|
|
|
110
119
|
---
|
|
111
120
|
|
|
112
121
|
### `scorecard_lookup_cip` <sub>tool</sub>
|
|
113
122
|
|
|
114
|
-
- Search by keyword or partial name
|
|
115
|
-
- Returns
|
|
123
|
+
- Search by nonblank keyword or partial name (default limit 20); requests up to 1,000 are accepted and served at a cap of 50. Totals count before slicing; exact-cap results are not truncated, and no matches return an empty collection with guidance.
|
|
124
|
+
- Dotted `11.07` and undotted `1107` queries are equivalent. Returns exact group titles and family identities from 186 current NCES CIP 2020 four-digit groups; verified six-digit descendant names act as keyword aliases, returning their canonical group. This curated set is a subset of the full taxonomy.
|
|
116
125
|
|
|
117
126
|
---
|
|
118
127
|
|
|
119
128
|
### `scorecard_list_fields` <sub>tool</sub>
|
|
120
129
|
|
|
121
|
-
- Search
|
|
130
|
+
- Search 78 curated offline field entries by nonblank query (default limit 30); requests up to 1,000 are accepted and served at a cap of 100. Totals count before slicing; no matches return an empty collection with guidance. Use before passing custom `fields` to `scorecard_get_school`.
|
|
122
131
|
- Returns field paths, descriptions, data types, categories, and API sorting support; `tip` flags results containing unsortable fields.
|
|
123
132
|
|
|
124
133
|
---
|
|
@@ -142,7 +151,7 @@ All resource data is also reachable via tools. Use `scorecard_search_schools` or
|
|
|
142
151
|
### `scorecard_compare_prompt` <sub>prompt</sub>
|
|
143
152
|
|
|
144
153
|
- Arguments: `school_names` (comma-separated list) and `focus` (`costs` | `outcomes` | `programs`), both required
|
|
145
|
-
-
|
|
154
|
+
- Costs/outcomes sequence school discovery, `scorecard_compare_schools`, profiles, and value analysis. Programs sequence school discovery, CIP lookup, and `scorecard_get_programs` per school; compare matching credentials using returned earnings, cumulative debt, and IPEDS awards in the two pooled debt-cohort years. Missing values and award-year dates remain unknown.
|
|
146
155
|
|
|
147
156
|
## Features
|
|
148
157
|
|
|
@@ -153,18 +162,37 @@ College Scorecard-specific:
|
|
|
153
162
|
- 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
|
|
154
163
|
- Program-level earnings: median earnings of graduates working and not enrolled 1 year after their highest credential, per school × CIP code × credential level
|
|
155
164
|
- Field pre-selection per tool — curated field sets appropriate to each tool's purpose; optional `fields` override for custom queries
|
|
156
|
-
- Embedded CIP
|
|
165
|
+
- Embedded CIP taxonomy (186 groups) and field catalog (78 fields) served offline
|
|
157
166
|
- Geographic filtering via U.S. zip code + distance radius
|
|
158
167
|
|
|
159
168
|
Agent-friendly output:
|
|
160
169
|
|
|
161
|
-
-
|
|
170
|
+
- Availability distinguishes numbers (including zero), unknown-cause missing values, and explicit `PS` / `PrivacySuppressed` provider markers. Confirmed privacy suppression does not identify its particular cause.
|
|
162
171
|
- Derived metrics alongside source figures in `scorecard_value_analysis` — agents can verify arithmetic and branch on computed values, not raw numbers
|
|
163
|
-
-
|
|
172
|
+
- Ordinal ranks in `scorecard_compare_schools` place each school's metric values within the comparison set
|
|
164
173
|
- School sorting uses indexed API fields; check `scorecard_list_fields` before choosing a sort expression. Six-year earnings does not support API sorting. Program earnings ordering applies within each fetched school page.
|
|
174
|
+
- Searches echo normalized effective selectors and pagination defaults on both output surfaces, distinguishing no upstream matches, exhausted pages, and locally filtered program pages. Blank optional selectors are unset; CIP precedence omits an ignored program name from the echo.
|
|
175
|
+
- Provider failures retain safe status/detail with distinct validation, authentication, throttling, timeout, and availability reasons. Permanent validation/authentication failures are not retried; resource failures include recovery and a request ID. Availability uses `api_error`; cancellation remains `RequestCancelled`.
|
|
165
176
|
|
|
166
177
|
## Getting started
|
|
167
178
|
|
|
179
|
+
### Public Hosted Instance
|
|
180
|
+
|
|
181
|
+
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:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"mcpServers": {
|
|
186
|
+
"college-scorecard-mcp-server": {
|
|
187
|
+
"type": "streamable-http",
|
|
188
|
+
"url": "https://college-scorecard.caseyjhand.com/mcp"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Self-Hosted / Local
|
|
195
|
+
|
|
168
196
|
Add the following to your MCP client configuration file. See [api.data.gov/signup](https://api.data.gov/signup/) for a free API key.
|
|
169
197
|
|
|
170
198
|
```json
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Preserve requested profile data and classify Scorecard failures with actionable recovery."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.3.0 — 2026-10-13
|
|
8
|
+
|
|
9
|
+
## Changed
|
|
10
|
+
|
|
11
|
+
- **Custom profile fields** now return real identity plus `selected_fields` and `absent_fields`. Migrate custom-mode reads from mapped properties to provider paths in `selected_fields`; nested program leaves retain the returned parent subtree, including sparse array positions and explicit nulls. ([#23](https://github.com/cyanheads/college-scorecard-mcp-server/issues/23))
|
|
12
|
+
- **Empty collections** succeed for existing schools without matching programs and offline catalog searches without matches, with recovery guidance instead of lookup errors. ([#36](https://github.com/cyanheads/college-scorecard-mcp-server/issues/36))
|
|
13
|
+
- **Provider failures** use distinct status-based codes and reasons with safe diagnostics, recovery, and request correlation. Permanent validation/authentication failures do not retry; deadlines cover response bodies and caller cancellation stops pending work. Resource HTTP 409 uses InvalidParams with `api_conflict`. ([#32](https://github.com/cyanheads/college-scorecard-mcp-server/issues/32), [#37](https://github.com/cyanheads/college-scorecard-mcp-server/issues/37))
|
|
14
|
+
- **Distribution maintenance** aligns npm registry launch metadata, adds hosted discovery, refreshes framework skills and checks, and moves Docker to Bun 1.4.2 → 1.4.3 with musl-only dependency pruning.
|
|
15
|
+
|
|
16
|
+
## Fixed
|
|
17
|
+
|
|
18
|
+
- **Required IDs and selectors** validate before fetch while retaining supported numeric string IDs, state lists, dotted CIP codes, ZIP-only searches, and decimal radii; optional blanks are unset and reversed ranges normalize. ([#22](https://github.com/cyanheads/college-scorecard-mcp-server/issues/22), [#32](https://github.com/cyanheads/college-scorecard-mcp-server/issues/32))
|
|
19
|
+
- **HBCU status** reads `school.minority_serving.historically_black` and preserves true, false, and unknown values. ([#29](https://github.com/cyanheads/college-scorecard-mcp-server/issues/29))
|
|
20
|
+
- **Batch profiles and catalogs** deduplicate IDs before the 100-ID serving cap, distinguish missing processed IDs from unchecked excess, and count catalog matches before slicing with accurate truncation and narrowing guidance. ([#33](https://github.com/cyanheads/college-scorecard-mcp-server/issues/33), [#31](https://github.com/cyanheads/college-scorecard-mcp-server/issues/31))
|
|
21
|
+
- **Search context** echoes effective normalized selectors and pagination defaults, with distinct notices for no upstream matches, exhausted pages, and locally filtered program pages. ([#36](https://github.com/cyanheads/college-scorecard-mcp-server/issues/36))
|
|
22
|
+
|
|
23
|
+
## Dependencies
|
|
24
|
+
|
|
25
|
+
- `@cyanheads/mcp-ts-core` ^0.13.10 → ^0.13.15
|
|
26
|
+
- `pino-pretty` ^13.1.3 → ^13.2.0
|
|
27
|
+
- `@biomejs/biome` ^2.5.14 → ^2.5.15
|
|
28
|
+
- `@types/node` ^26.6.3 → ^26.6.5
|
|
29
|
+
- `ignore` ^7.0.10 → ^7.0.12
|
|
30
|
+
- `tsc-alias` ^1.9.5 → ^1.9.7
|
|
31
|
+
- `vitest` ^5.0.2 → ^5.0.3
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Correct Scorecard earnings, availability, and program comparisons."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.4.0 — 2026-10-14
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`scorecard_search_programs`** accepts integer `credential_level` selectors before school pagination and retains provider credential levels/titles, including future numeric levels; missing identity remains absent. ([#26](https://github.com/cyanheads/college-scorecard-mcp-server/issues/26))
|
|
12
|
+
- **`scorecard_value_analysis`** discloses `effective_net_price`, `net_price_basis`, requested income/bracket, and the overall-price fallback when a bracket estimate is unavailable. ([#35](https://github.com/cyanheads/college-scorecard-mcp-server/issues/35))
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
|
|
16
|
+
- **`scorecard_get_earnings.years`** selects API data-file start years, validated to 1996–2025; valid files without observations succeed. Per-metric context supplies verified entry cohorts, measurement years, and dollar basis without re-inflation. ([#25](https://github.com/cyanheads/college-scorecard-mcp-server/issues/25))
|
|
17
|
+
- **Availability** distinguishes available numbers, unknown-cause missing data, and explicit privacy markers. Consumers must use availability fields for missing data; `suppressed` flags/counts now require confirmed privacy suppression, and aggregate earnings suppression requires every current metric explicitly marked. ([#38](https://github.com/cyanheads/college-scorecard-mcp-server/issues/38))
|
|
18
|
+
- **Provider metrics** accept explicit privacy sentinels and reject unexpected values with `ServiceUnavailable` / `api_error` plus recovery guidance.
|
|
19
|
+
|
|
20
|
+
## Removed
|
|
21
|
+
|
|
22
|
+
- **`current.earnings_6yr_female_median`** is replaced by `earnings_6yr_non_male_median`; migrate consumers to the provider's non-male population. Unsupported `percent_greater_than_100000` and `mean_annual_increment` catalog entries are removed. ([#24](https://github.com/cyanheads/college-scorecard-mcp-server/issues/24))
|
|
23
|
+
|
|
24
|
+
## Fixed
|
|
25
|
+
|
|
26
|
+
- **Earnings projections** use real percentile and non-male/male paths; profiles render available P75 values even when P25 is absent.
|
|
27
|
+
- **Earnings descriptions** identify federally aided undergraduate entrants working and not enrolled, regardless of completion.
|
|
28
|
+
- **`scorecard_compare_prompt`** uses CIP lookup and per-school program retrieval for programs focus, comparing matching credentials with earnings, cumulative debt, and pooled-cohort IPEDS awards. ([#27](https://github.com/cyanheads/college-scorecard-mcp-server/issues/27))
|
|
29
|
+
- **`scorecard_compare_schools`** uses competition ranks (1, 1, 3), leaves unavailable values unranked, and names tied leaders. ([#34](https://github.com/cyanheads/college-scorecard-mcp-server/issues/34))
|
|
30
|
+
- **`scorecard_lookup_cip`** reconciles 186 curated four-digit groups to NCES CIP 2020, resolves verified descendant aliases, and accepts undotted codes. ([#30](https://github.com/cyanheads/college-scorecard-mcp-server/issues/30))
|
|
31
|
+
- **Packaging** declares the required Scorecard API key for HTTP npm installs and excludes development tests/fixtures from desktop bundles.
|
package/dist/data/cip-codes.d.ts
CHANGED
|
@@ -13,11 +13,16 @@ export interface CipEntry {
|
|
|
13
13
|
/** Standard title for the program (e.g. "Computer Science") */
|
|
14
14
|
title: string;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
16
|
+
/** Curated current four-digit groups, with exact NCES CIP 2020 titles and family names. */
|
|
17
17
|
export declare const CIP_CODES: CipEntry[];
|
|
18
18
|
/**
|
|
19
19
|
* Search CIP codes by keyword — matches against code, title, family title.
|
|
20
20
|
* Returns up to `limit` results (default 20).
|
|
21
21
|
*/
|
|
22
22
|
export declare function searchCipCodes(query: string, limit?: number): CipEntry[];
|
|
23
|
+
/** Verified six-digit descendants used only as keyword aliases for their four-digit group. */
|
|
24
|
+
export declare const CIP_ALIASES: Record<string, Array<{
|
|
25
|
+
code: string;
|
|
26
|
+
title: string;
|
|
27
|
+
}>>;
|
|
23
28
|
//# sourceMappingURL=cip-codes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cip-codes.d.ts","sourceRoot":"","sources":["../../src/data/cip-codes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,
|
|
1
|
+
{"version":3,"file":"cip-codes.d.ts","sourceRoot":"","sources":["../../src/data/cip-codes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,2FAA2F;AAC3F,eAAO,MAAM,SAAS,EAAE,QAAQ,EAimC/B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,QAAQ,EAAE,CAqCpE;AAED,8FAA8F;AAC9F,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B9E,CAAC"}
|