This page covers what a script author, agent builder, or contributor needs from edstem-cli beyond the human-facing walkthroughs: exact exit codes, config keys and environment variables, non-interactive flags, retry behavior, and how to self-host the MCP (Model Context Protocol) server.

Error codes and exit codes

Every error prints once to stderr and sets the process exit code. See Errors and exit codes for the shared model; the table below covers what actually produces each code in edstem-cli. An unrecognized or ambiguous unit code is a usage error (exit 2) — the CLI is validating against enrolments it already has. A numeric unit ID that doesn’t match any enrolment is a not-found error (exit 4) instead, since that requires asking Ed.

Environment variables and config keys

Config file

edstem-cli reads YAML from ~/.config/edstem-cli/config.yaml by default. Override the path with EDSTEM_CONFIG. A missing file is not an error — every key falls back to its default.
A non-integer or non-positive fetch.count, a non-integer or negative rateLimit.maxRetries (0 is valid and disables retries), or a non-positive rateLimit.retryBaseDelay, is ignored in favor of the default rather than rejected.

Environment variables

Precedence

  • Token: EDSTEM_TOKEN, if set and non-empty, always wins over the saved token file — even right after auth login writes a new file. Running auth login while EDSTEM_TOKEN is set still verifies and saves the pasted token to the file, but the environment variable keeps winning at runtime until you unset it.
  • API base URL: EDSTEM_BASE_URL, if set, overrides the config file’s value; there’s no config-file key for it.
  • Config path: EDSTEM_CONFIG, if set, replaces the default ~/.config/edstem-cli/config.yaml path outright, rather than merging with it.

Non-interactive use

Pipe a token in instead of the interactive prompt:
auth login does not require --yes or a saved token beforehand: passing a token, piped or typed, is already an explicit action.

Retries and rate limits

A read request that comes back 429, 502, 503, or 504 is retried automatically, up to rateLimit.maxRetries times, waiting longer between each attempt. If Ed asks the CLI to wait a specific amount of time first, the CLI waits at least that long instead, whichever is larger. Writes — threads send, replies send, lessons mark-read, slides submit, auth logout — are never retried automatically. Retrying a write that may have already succeeded risks duplicating it; see Posting and Mutations.

Self-deploying the Ed Worker

This is the same source the hosted server at https://edstem.tuuhub.com/mcp runs. Deploying it yourself gives you your own endpoint, your own Worker variables, and the static-token mode below as an alternative to OAuth. See MCP server for what the hosted service stores instead.
A self-deployed Worker exposes two endpoints:

Worker variables

Static token mode

A self-deployed Worker also accepts a static Ed token directly, instead of OAuth:
  • The client sends the Ed token in Authorization: Bearer <token> or X-API-Key: <token> on every request, over HTTPS.
  • The Worker verifies that token against Ed and uses it for the duration of that request; verification results are cached per MCP_TOKEN_CACHE_TTL_SECONDS above.
  • The Worker doesn’t store this token anywhere — it’s used for that one request and then forgotten.
  • The Worker does not write the token header to logs.
This mode is a convenience for clients that can send custom headers but can’t do MCP OAuth; it’s not part of the MCP OAuth flow itself.

MCP tools

Every tool’s name, arguments, and whether it writes are catalogued at Ed Discussion MCP tools. The list_activity tool accepts the same values as edstem activity’s --filter flag (all, thread, answer, comment), in its filterType field. Posting tools (create_thread, reply_thread) are off by default; enable them with EDSTEM_ALLOW_POSTING=1 locally or MCP_ALLOW_POSTING=1 on a self-deployed Worker — see Environment variables and config keys and Self-deploying the Ed Worker above.

Connect a client

Client-specific setup for Codex, Claude, ChatGPT, and others.