scrumdo-mcp
Connect Claude Code, Codex, Cursor, OpenCode, Antigravity, GitHub Copilot, and other MCP hosts to your ScrumDo / Spryng boards over local stdio.
The default connection is a personal smcp_ token and the collaborate
tool profile: read, comment, propose, and follow events as you. A broad
organization API key is not equivalent human identity.
Full setup and host-specific guidance: ScrumDo MCP documentation.
Installation
pip install scrumdo-mcp
Requires Python 3.11+. The process speaks MCP over stdio (scrumdo-mcp).
That local path is the supported compatibility floor.
The hosted Django endpoint
POST https://app.spryng.io/api/scrumdo/organizations/<org>/mcp/rpc/ is a
transitional bearer beta. It is not OAuth and is not official
Streamable HTTP general availability. Prefer stdio until remote GA.
Get a personal token
- Sign in at https://app.spryng.io.
- Open your organization → Settings → MCP Tokens.
- Create a named personal connection and copy the secret once.
Personal tokens start with smcp_. Do not use Settings → API Tokens
(OrgAPIKey) for human AI-client collaboration.
Your org and project slugs are the path segments in
app.spryng.io/my-company/engineering.
Local stdio (supported)
Replace the placeholder. Never commit a real token.
Cursor — ~/.cursor/mcp.json
{
"mcpServers": {
"scrumdo": {
"command": "scrumdo-mcp",
"env": {
"SCRUMDO_TOKEN": "smcp_YOUR_PERSONAL_TOKEN",
"SCRUMDO_ORG": "your-org-slug",
"SCRUMDO_PROJECT": "your-default-project-slug",
"SCRUMDO_BASE_URL": "https://app.spryng.io",
"SCRUMDO_MCP_PROFILE": "collaborate",
"SCRUMDO_CLIENT_NAME": "cursor"
}
}
}
}
Claude Code — ~/.claude.json
Same mcpServers shape as Cursor. Prefer the CLI so you do not edit
~/.claude/claude.json by mistake:
claude mcp add scrumdo \
-e SCRUMDO_TOKEN=smcp_YOUR_PERSONAL_TOKEN \
-e SCRUMDO_ORG=your-org-slug \
-e SCRUMDO_PROJECT=your-default-project-slug \
-e SCRUMDO_BASE_URL=https://app.spryng.io \
-e SCRUMDO_MCP_PROFILE=collaborate \
-e SCRUMDO_CLIENT_NAME=claude-code \
-- scrumdo-mcp
Codex — ~/.codex/config.toml
[mcp_servers.scrumdo]
command = "scrumdo-mcp"
[mcp_servers.scrumdo.env]
SCRUMDO_TOKEN = "smcp_YOUR_PERSONAL_TOKEN"
SCRUMDO_ORG = "your-org-slug"
SCRUMDO_PROJECT = "your-default-project-slug"
SCRUMDO_BASE_URL = "https://app.spryng.io"
SCRUMDO_MCP_PROFILE = "collaborate"
SCRUMDO_CLIENT_NAME = "codex"
Restart Codex after changing the token so the stdio process picks up the new env.
OpenCode — opencode.json
OpenCode uses a top-level mcp object (not mcpServers):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"scrumdo": {
"type": "local",
"command": ["scrumdo-mcp"],
"enabled": true,
"environment": {
"SCRUMDO_TOKEN": "smcp_YOUR_PERSONAL_TOKEN",
"SCRUMDO_ORG": "your-org-slug",
"SCRUMDO_PROJECT": "your-default-project-slug",
"SCRUMDO_BASE_URL": "https://app.spryng.io",
"SCRUMDO_MCP_PROFILE": "collaborate",
"SCRUMDO_CLIENT_NAME": "opencode"
}
}
}
}
Antigravity
Use the same mcpServers shape as Cursor and set
SCRUMDO_CLIENT_NAME=antigravity. The connector still enforces the personal
smcp_ credential and collaborate profile server-side.
GitHub Copilot Chat — .vscode/mcp.json
Use Copilot Chat in Agent mode with a local stdio server:
{
"servers": {
"scrumdo": {
"type": "stdio",
"command": "scrumdo-mcp",
"env": {
"SCRUMDO_TOKEN": "smcp_YOUR_PERSONAL_TOKEN",
"SCRUMDO_ORG": "your-org-slug",
"SCRUMDO_PROJECT": "your-default-project-slug",
"SCRUMDO_BASE_URL": "https://app.spryng.io",
"SCRUMDO_MCP_PROFILE": "collaborate",
"SCRUMDO_CLIENT_NAME": "github-copilot-vscode"
}
}
}
}
GitHub Copilot CLI — ~/.copilot/mcp-config.json
{
"mcpServers": {
"scrumdo": {
"type": "stdio",
"command": "scrumdo-mcp",
"args": [],
"env": {
"SCRUMDO_TOKEN": "smcp_YOUR_PERSONAL_TOKEN",
"SCRUMDO_ORG": "your-org-slug",
"SCRUMDO_PROJECT": "your-default-project-slug",
"SCRUMDO_BASE_URL": "https://app.spryng.io",
"SCRUMDO_MCP_PROFILE": "collaborate",
"SCRUMDO_CLIENT_NAME": "github-copilot-cli"
}
}
}
}
GitHub Copilot cloud agent is not this personal-machine flow. Do not put a
person's smcp_ token into a shared repository or organization Agent secret.
For CI and shared automation, the account owner creates a service account
(Settings → MCP Tokens → Service accounts) and uses its svc_ token instead.
Hosted remote (beta, not GA)
You can point a remote-capable host at:
https://app.spryng.io/api/scrumdo/organizations/<org>/mcp/rpc/
with Authorization: Bearer smcp_….
This is the current Workbench bearer JSON-RPC POST. It is not OAuth 2.1, Protected Resource Metadata, or full Streamable HTTP GA. Treat it as beta. Local stdio remains the compatibility floor.
Microsoft 365 Copilot through Copilot Studio is not supported by this beta endpoint. It requires the planned standards-conformant Streamable HTTP endpoint and delegated per-user OAuth; a shared API key is not equivalent human identity.
Tool profiles
| Profile | Env | What the model sees |
|---|---|---|
| collaborate (default) | SCRUMDO_MCP_PROFILE=collaborate or unset |
Identity/capability discovery and get_workflow_context; search across everything the person may see (cards, tasks, comments, OKRs, key results, sprints, specs, people… with the server's type: / board: / is: / due: filters); card search/read and handoff brief; comments and blackboard notes; the team loop — complete/reopen tasks, block/unblock, log hours, policy-checked column moves, allowlisted fields, pull request links; the workflow ledger and its undo; the org loop on Business — portfolio decisions, escalations, the done rule; spec read and publish-as-proposal; the product specs a board was given (list_board_specs, read_spec_document); proposal read/revise/request-changes; decision inbox and challenge status; run read/status; room work types and OKRs; governed skill catalog reads (list_skills, load_skill); delivery evidence proofs (post_delivery_proof, get_delivery_proof); meaning drift (drift_status_get, drift_observations_list, drift_signals_get, proof_readiness_get, outcome_bindings_list, drift_automation_list, drift_automation_preview, drift_evaluate, and the person-confirmed drift_acknowledge and drift_automation_propose); events.wait / events.ack. Which writes a connection may make is the server's role template for the person (crew, room manager, portfolio manager, owner, reader) — not this list. |
| compat | SCRUMDO_MCP_PROFILE=compat |
Maintainers and service connections only; refused at startup on a personal (smcp_) token. All registered tools, including deletes, webhooks, inbox wait_for_notifications, direct spec writes, and run/loop writes. Aliases: full, legacy, all. Automation runs the team loop on the default profile. |
Call get_mcp_capabilities() for the exact tool_count and names on your
process. This package version registers 116 tools on collaborate and
180 on compat (one more on either profile when --skill is set). At
startup the server's mcp/capabilities/ narrows that to your role, plan and
board: role-template writes (workflow) and the meaning drift tools
(drift: none where drift is off, the reads plus your role's writes where it
is on). Compat restores the large surface only for service and test
connections.
Meaning drift human writes (drift_acknowledge, drift_automation_propose)
never count because an agent asked: the server turns each into a
confirmation the person answers. If your MCP host supports elicitation the
person is asked right there; otherwise they answer in ScrumDo (the card's
Drift tab or the notification on their phone) and you call the tool again
with confirmation_id, or wait for the drift.confirmation.answered event.
Deprecated / inbox-coupled: wait_for_notifications stays in compat
only. New clients should use events.wait / events.ack (connection cursor,
independent of the web inbox).
Session skill packs (--skill)
Pin one governed skill pack to the whole session:
scrumdo-mcp --skill privacy # or: SCRUMDO_SKILL=privacy scrumdo-mcp
Accepted names are the full slugs and their short aliases — privacy
(ferpa-privacy-guard), spec-audit (spec-gap-auditor), flow-analyst
(flow-friction-analyst), wsjf (wsjf-economic-estimator). The CLI flag
wins over the SCRUMDO_SKILL env twin; an unknown name is a startup error
listing the valid names. Startup stays fully offline: the server only adds
an instructions note plus a load_active_skill() tool, and the skill's
governed content (content_md, approved versions only) is fetched from the
hosted skills endpoint lazily at that tool's first call, then memoized. On
any profile, list_skills / load_skill let a session browse and load the
rest of the org's published packs manually.
The post_delivery_proof / get_delivery_proof pair records and reads
signed Delivery Evidence Proofs on a card. The server mints the
signature and requires a human sign-off — this client never sends a
signature key, and an agent-principal session receives the server's refusal
as a closed error envelope (signature_not_accepted,
delivery_proof_required, …).
Identity
- Personal
smcp_token →credential_kind=personal_mcp, human collaboration. - Broad OrgAPIKey →
org_api_key. The server refuses to start unless you setSCRUMDO_ALLOW_ORG_API_KEY=1. That flag is an explicit, documented compatibility mode. It does not make the key equivalent to a person. SCRUMDO_AGENT_RUN_IDdescribes a run-scoped session, not human identity.- Service account
svc_token →credential_kind=service_account. A machine identity owned by the organization: it reads the boards it was given and writes only the actions the account owner granted. It never speaks for a person (no comments, proposals or drift acknowledgements), andcompatis allowed because the server shapes and enforces it either way.
Events
events.wait(after?, timeout_s, limit) and events.ack(cursor) follow the
frozen connection-cursor contract. Envelopes are schema_version 1 with a
safe_summary only. If the cursor is behind the 30-day retention floor the
adapter returns cursor_expired plus a handoff instruction.
Security
- Create and revoke tokens at Settings → MCP Tokens, not API Tokens.
- The secret is shown once. Do not put a real token in chat, git, tests, or docs.
- Default collaborate omits deletes, webhook admin, org config, secrets, deployment, and direct accepted-spec writes.
- Remote API origins must use HTTPS. Plain HTTP is accepted only for localhost and loopback addresses used during local development.
- Compat-profile local attachment uploads are disabled until
SCRUMDO_ATTACHMENT_ROOTSexplicitly allows one or more directories. Resolved paths outside those roots, including symlink escapes, are rejected. - Concurrent writes that this package translates carry
Idempotency-Key/expected_version(andIf-Match) when callers supply them. Closed error codes includenot_found_or_denied,wrong_organization,connection_revoked,grant_required,human_step_up_required,stale_resource,duplicate_command,rate_limited,cursor_expired,unsupported_client_capability. - Revoke a connection if a machine is lost. The next operation fails.
Environment variables
| Variable | Default | Description |
|---|---|---|
SCRUMDO_TOKEN |
— | Required. Personal smcp_ token from Settings → MCP Tokens |
SCRUMDO_ORG |
— | Organization slug |
SCRUMDO_PROJECT |
— | Default project slug |
SCRUMDO_BASE_URL |
https://app.spryng.io |
API base URL |
SCRUMDO_MCP_PROFILE |
collaborate |
collaborate or compat |
SCRUMDO_ALLOW_ORG_API_KEY |
unset | Deprecated opt-in to start with an OrgAPIKey |
SCRUMDO_AGENT_RUN_ID |
— | Optional run attribution header |
SCRUMDO_CLIENT_NAME |
mcp |
Host name (codex, claude-code, cursor, opencode, antigravity, github-copilot-vscode, or github-copilot-cli) |
SCRUMDO_ATTACHMENT_ROOTS |
unset | Compat-only local attachment allowlist; use the platform path separator for multiple directories |
SPRYNG_LOOP_ID |
— | Optional loop attribution |
Legacy SPRYNG_* names are still accepted as aliases.
What you can do (collaborate)
"What cards need my attention?"
"Read ENG-42 and the handoff brief"
"What work types can I use on this room?"
"What OKRs is this room assigned?"
"Comment on ENG-42 that the proposal is up"
"Publish this spec as a proposal on ENG-42"
"What product specs was this board given? Read the checkout one"
"Wait for the next board event for this connection"
Direct column moves, webhook admin, and accepted-spec overwrites are not on the default profile.
Live conformance (opt-in)
The package includes a stdio-protocol harness (python -m spryng_mcp.conformance).
The default hermetic mode launches two real scrumdo-mcp processes against an
in-process HTTP fixture. It does not talk to Django.
The two-user live run is opt-in and fail-closed. It never reads tokens from
source or fixtures. Export personal smcp_ values only in the process
environment (never commit them):
| Variable | Required for live | Purpose |
|---|---|---|
SCRUMDO_LIVE_CONFORMANCE |
yes (1) |
Opt-in gate |
SCRUMDO_ALICE_TOKEN |
yes | Personal connection A |
SCRUMDO_BOB_TOKEN |
yes | Personal connection B |
SCRUMDO_READONLY_TOKEN |
yes | Read-only / guest control |
SCRUMDO_UNRELATED_TOKEN |
yes | Unrelated-room control |
SCRUMDO_REVOKED_TOKEN |
yes | Already-revoked personal token |
SCRUMDO_TARGET_RUN_ID |
yes | AgentRun id under test (do not reuse SCRUMDO_AGENT_RUN_ID) |
SCRUMDO_BASE_URL |
no | Default http://127.0.0.1:8018 |
SCRUMDO_ORG |
no | Default test-account-a |
SCRUMDO_PROJECT |
no | Default room project slug |
SCRUMDO_CARD_REF |
no | Default AG-2 |
SCRUMDO_FOREIGN_ORG |
no | Other-org slug for closed denial |
SCRUMDO_ALICE_CLIENT / SCRUMDO_BOB_CLIENT |
no | Distinct client names |
SCRUMDO_COPILOT_TOKEN |
no | Defaults to Alice; use with Copilot client name |
SCRUMDO_ORG_API_KEY |
no | Negative OrgAPIKey case |
SCRUMDO_WEB_SESSIONID |
no | Django session cookie for s8 web-inbox independence |
SCRUMDO_WEB_CSRFTOKEN |
no | CSRF token paired with the web session |
SCRUMDO_WEB_SESSION_COOKIE_NAME |
no | Session cookie name; defaults to sessionid (Spryng uses sprsession) |
python -m spryng_mcp.conformance hermetic
SCRUMDO_LIVE_CONFORMANCE=1 python -m spryng_mcp.conformance live
If a required live name is missing, the command exits 2 with a missing-fixture message that lists names only.
Remote MCP conformance (AG-07C)
Hermetic delegated-OAuth and hosted Streamable HTTP proof lives in this
package. It uses official MCP Inspector, NAV mock-oauth2-server, and
oidc-provider as test-only processes. It is not the future
real-Microsoft-tenant AG-07D gate, and it does not enable Microsoft 365
Copilot.
See docs/AG-07C-RUNBOOK.md. One command:
./scripts/ag07c-gate
Development (maintainers)
pip install -e ".[dev]"
pytest tests/ -v
python -m spryng_mcp.conformance hermetic
Source access is restricted to maintainers. Package users should install the public wheel from PyPI and use the public documentation linked above.
License
MIT
Metadata
Release files for scrumdo-mcp 0.14.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scrumdo_mcp-0.14.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / scrumdo_mcp-0.14.0-py3-none-any.whl
| Download URL | scrumdo_mcp-0.14.0-py3-none-any.whl |
|---|---|
| Size | 143.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7d854f4a582e197ece5684f3fd7954441423d188f4b9ac74670df465ae53de7c
|
|
BLAKE2b-256 checksum How to use checksums |
346148d10f984645955cdf4b3e217ac0432f8b67942b82c5765e409c9a2b10f9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log