Content
# edstem-cli
CLI and MCP access to Ed Discussion for people, scripts, and agents.
[](https://www.npmjs.com/package/edstem-cli)
[](https://www.npmjs.com/package/edstem-cli)
[](https://github.com/bunizao/edstem-cli/actions/workflows/ci.yml)
[](https://nodejs.org/)
[](https://bun.sh/)
[](https://modelcontextprotocol.io/)
[](#quiz-answering-beta)
[](LICENSE)
One package provides a human- and agent-friendly CLI plus local and hosted MCP servers:
| Surface | What it does | Runtime | Authentication |
| ---------------- | ------------------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------------------- |
| `edstem` **CLI** | Query courses, lessons, threads, and activity as compact JSON or Markdown; answer quizzes in beta | Node.js 20+ or Bun | Local Ed API token |
| **local MCP** | Expose the same Ed operations to local MCP clients over stdio | Node.js 20+ or Bun | Local Ed API token |
| **Hosted MCP** | Offer remote Streamable HTTP access for shared deployments and remote MCP clients | Bun | OAuth at [`edstem.tuuhub.com/mcp`](https://edstem.tuuhub.com/mcp) |
Node.js 20+ is the supported npm baseline. The CLI and local MCP bundles are also Bun-compatible; the hosted server requires Bun for `Bun.serve` and `bun:sqlite`.
## Installation
```bash
npm i -g edstem-cli
bun add -g edstem-cli # if you like Bun🥟
```
Create a token at [edstem.org/settings/api-tokens](https://edstem.org/settings/api-tokens). The CLI also reads `~/.config/edstem-cli/token`.
```bash
export ED_API_TOKEN="your-token"
edstem courses
```
A course table in the terminal means you're set!
## CLI
`edstem` is designed as an **AI-native** CLI, so JSON is the default. List commands return compact summaries; detail commands fetch full records and can export Markdown. The examples below use the globally installed command; without installing, prefix them with `npx edstem-cli` or `bunx edstem-cli`.
Cases:
```bash
edstem courses
edstem threads 12345 --max 20 --fields id,number,title,flags
edstem thread 12345#42
edstem lessons 12345 --module "Week 2"
edstem thread 67890 --md --output thread.md
```
Quiz and lesson-progress commands mutate your Ed state. Run them only when that is intentional:
```bash
edstem lessons read 12345 Pre-Reading
```
### Quiz answering (beta)
`edstem` can inspect quiz questions and saved responses, answer single- or multi-select questions, amend an answer, and submit the completed slide.
```bash
# Inspect a quiz slide and its saved responses.
edstem lessons quiz 4401
edstem lessons quiz 4401 --responses
# Save an answer. Repeat --choice for multi-select questions.
edstem lessons quiz 4401 --answer 991 --choice 2
edstem lessons quiz 4401 --answer 991 --choice 2 --choice 4 --amend
# Submit all saved answers for the slide.
edstem lessons quiz 4401 --submit
```
This feature is beta because Ed's quiz endpoints are not part of a stable public API. Review the selected question and choices before writing, and treat `--submit` as final unless the course allows another attempt.
Use `edstem --help` for the complete command reference. Raw Ed XML stays out of thread JSON unless you pass `--include-html`.
## MCP
### Local
Configure an MCP client to launch the stdio server:
```json
{
"mcpServers": {
"edstem": {
"command": "edstem-mcp",
"env": {
"ED_API_TOKEN": "your-token"
}
}
}
}
```
### Hosted
Add `https://edstem.tuuhub.com/mcp` as a Streamable HTTP MCP server. Your client opens the OAuth flow, where you provide an Ed API token and approve the requested access.
Local adapters receive your Ed token directly. The hosted server encrypts tokens at rest, maps them to OAuth identities, and requires a separate write scope for quiz and lesson-progress mutations.
## Agent skill
```bash
npx skills add https://github.com/bunizao/edstem-cli
# Inspect metadata or regenerate the tracked reference.
edstem skills
edstem skills generate
```
[SKILL.md](https://github.com/bunizao/edstem-cli/blob/main/SKILL.md) is the canonical agent reference. Its CLI table and MCP tool list are generated from the implementation, and CI rejects drift.
## Self-hosting
The hosted adapter uses Bun, Streamable HTTP, OAuth, encrypted Ed tokens, and SQLite.
```bash
cp .env.example .env
# Set MASTER_KEY and PUBLIC_BASE_URL.
docker compose up -d
```
The image exposes `/healthz`, `/readyz`, and `/mcp`. SQLite data lives in the `app_data` volume.
## Development
```bash
npm install
npm run check
npm test
npm run build
npm run pack:check
npm run pack:smoke
```
`npm test` runs Vitest for the Node.js CLI and local MCP server, then Bun tests for remote OAuth, security, SQLite, and reconnect behavior.
## License
[MIT](LICENSE). See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for migrated remote MCP attribution.