ed-discussion-mcp
An MCP server that lets AI agents (Claude Code, Claude Desktop, Cursor, VS Code, Codex and others) search and read your Ed Discussion courses. You can then ask things like:
- "When is the CS 180 midterm, and has the room changed?"
- "Was the HW3 deadline extended?"
- "What should I know before starting homework 4?"
Read-only and local. The server runs on your own machine, signs in with your own Ed API token, and only reads from Ed: it never posts, edits or reacts. Your token is sent only to Ed.
Keep in mind that the agent sees whatever your Ed account can see, including private threads. Thread content it reads goes to the AI model your client uses, just as if you had pasted it into the chat.
This project uses Ed's unofficial API, so an Ed update could break it. It is not affiliated with Ed.
Tools
| Tool | What it does |
|---|---|
list_courses |
Your courses in Ed dashboard order (archived ones optional) |
course_overview |
A course's categories, pinned threads, recent announcements and recent threads |
search_threads |
Keyword search using Ed's own search (titles, bodies and replies) |
list_threads |
Newest threads, filtered by category, type, pinned, staff author or date |
get_thread |
A full thread with nested answers and comments, by id or by #number |
Every result includes the author's role (student or staff), timestamps, whether the post was edited, and a link to the thread.
Setup
1. Install uv
The server runs with uv's uvx, which downloads and runs it in an isolated environment; there is nothing else to install.
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
2. Create an Ed API token
Go to edstem.org/us/settings/api-tokens (use your own region in place of us), create a token, and copy it.
3. Add the server to your client
Most MCP clients accept this standard config. Put your token in place of your_token:
{
"mcpServers": {
"ed-discussion": {
"command": "uvx",
"args": ["--from", "git+https://github.com/GalacticQuasar/ed-discussion-agent", "ed-discussion-mcp"],
"env": { "ED_API_TOKEN": "your_token" }
}
}
}
Your token goes in your client's own config file on your machine. Don't put it in a file you commit or share.
Claude Code
claude mcp add ed-discussion --scope user -e ED_API_TOKEN=your_token -- \
uvx --from git+https://github.com/GalacticQuasar/ed-discussion-agent ed-discussion-mcp
Claude Desktop
Open Settings → Developer → Edit Config, add the standard config to claude_desktop_config.json, and restart Claude Desktop.
Cursor
Add the standard config to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project), or open Settings → MCP → Add new MCP Server.
VS Code (GitHub Copilot)
Run MCP: Open User Configuration from the Command Palette and add the server. VS Code uses servers rather than mcpServers, and can ask for your token once and store it securely instead of keeping it in the file:
{
"inputs": [
{ "type": "promptString", "id": "ed-api-token", "description": "Ed API token", "password": true }
],
"servers": {
"ed-discussion": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "git+https://github.com/GalacticQuasar/ed-discussion-agent", "ed-discussion-mcp"],
"env": { "ED_API_TOKEN": "${input:ed-api-token}" }
}
}
}
Codex
codex mcp add ed-discussion --env ED_API_TOKEN=your_token -- \
uvx --from git+https://github.com/GalacticQuasar/ed-discussion-agent ed-discussion-mcp
Or add it to ~/.codex/config.toml:
[mcp_servers.ed-discussion]
command = "uvx"
args = ["--from", "git+https://github.com/GalacticQuasar/ed-discussion-agent", "ed-discussion-mcp"]
env = { ED_API_TOKEN = "your_token" }
Other clients: any client that can launch a local MCP server works. Give it the uvx command and arguments from the standard config, with ED_API_TOKEN set in its environment. For clients that only connect to servers over HTTP, see HTTP mode.
Configuration
| Variable | Default | Description |
|---|---|---|
ED_API_TOKEN |
Your Ed API token. | |
ED_REGION |
us |
Your Ed region, as in your Ed URL (edstem.org/us/...), e.g. au or eu. |
ED_EMAIL, ED_PASSWORD |
Alternative to ED_API_TOKEN: sign in with email and password. Ignored when ED_API_TOKEN is set. |
|
ED_MCP_AUTH_TOKEN |
random | HTTP mode only: the bearer token clients must send. |
HTTP mode
By default, your client launches the server and talks to it over stdio. Some clients, such as Open WebUI, instead connect to a server that is already running at a URL. For those, start the server yourself with --http:
ED_API_TOKEN=your_token ED_MCP_AUTH_TOKEN=choose-a-long-random-secret \
uvx --from git+https://github.com/GalacticQuasar/ed-discussion-agent ed-discussion-mcp --http
It serves MCP over Streamable HTTP at http://127.0.0.1:8001/mcp (change it with --host and --port). Point your client at that URL and set the header Authorization: Bearer <your ED_MCP_AUTH_TOKEN>; most clients have a bearer token or headers field for this. Requests without the token are rejected. If you leave ED_MCP_AUTH_TOKEN unset, the server makes up a token and prints it at startup, but it changes every time the server restarts.
For example, in Open WebUI go to Admin Settings → External Tools, add a server of type MCP (Streamable HTTP), enter the URL, and choose Bearer authentication with your token.
The server listens only on your own machine (127.0.0.1) unless you pass --host. If your client runs in Docker (for example Open WebUI in Docker Desktop), start the server with --host 0.0.0.0 and use http://host.docker.internal:8001/mcp as the URL. That makes the server reachable from your network too, so the token is all that stands between it and your Ed account. Use a long random one.
Development
Requires uv.
git clone https://github.com/GalacticQuasar/ed-discussion-agent.git
cd ed-discussion-agent
uv sync
Put your credentials in a .env file in the repo root (it is gitignored):
ED_API_TOKEN=your_api_token
uv run --env-file .env ed-discussion-mcpruns the server from your working copy. Claude Code does this automatically through.mcp.jsonwhen you open the repo (approve the server when prompted).uvx --no-cache --from . ed-discussion-mcpruns it the way users will, from a fresh build.--no-cachematters here: without it, uvx reuses its first build of the local package even after you change the code.
The package lives in src/ed_discussion_mcp/: server.py defines the MCP tools, and ed_api.py handles credentials, regions and Ed's REST API.
Experiments
experiments/ holds prototypes that are not part of the package. They use the package's ed_api module and read credentials from .env. uv sync installs their dependencies.
uv run experiments/watch_posts.py [COURSE_ID ...]: watches for new posts in real time over Ed's websocket stream. With no arguments it asks which courses to watch.uv run experiments/main.py: a minimal web UI on port 8000 that lists a course's recent threads.uv run experiments/auth_flow.py: an interactive CLI that lists your courses and dumps a course's 30 newest threads.
License
Metadata
Release files for ed-discussion-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ed_discussion_mcp-0.1.0.tar.gz | 13.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ed_discussion_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.6 kB
Release files / ed_discussion_mcp-0.1.0.tar.gz
| Download URL | ed_discussion_mcp-0.1.0.tar.gz |
|---|---|
| Size | 13.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dc5e03fbc472f8d9220179202808f842649a738fc5e567bf37ddb8d1f47d8a92
|
|
BLAKE2b-256 checksum How to use checksums |
8c39f2b6e69b99fe71711d2f2790ae4219d35f8fcd7c9e84e361298ae4dd9460
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / ed_discussion_mcp-0.1.0-py3-none-any.whl
| Download URL | ed_discussion_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e77358c0cee6dfbe46a1607d2c545f0bfc2f0a6084e3bcb4a20ca169d9d57c18
|
|
BLAKE2b-256 checksum How to use checksums |
177d8f7e6c7fe01c2365f37252927c2ca130334454cb7040bd6901a89d033067
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for ed-discussion-mcp 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.