trackmcp
Back to directory
Jubstaaa

standup-mr

View on GitHub

Standup notes from merge request state, not commit logs. Reads GitLab or GitHub: what is ready, what is blocked, and why your pipeline is red.

0 stars TypeScriptOthers Updated Sep 2, 2026
claude-codeclideveloper-toolsgithubgitlabmcpmerge-requestspull-requestsstandup

Documentation

standup-mr

standup-mr MCP server
Listed on mcpservers.org

Standup notes from merge request state, not commit logs.

Most standup tools read your local `git log`. That answers "what did I type",

which is not what anyone asks in a standup. This one reads GitLab or GitHub:

what is ready to merge, what is blocked, what is waiting on you — and when a

pipeline is red, it opens the job log and tells you why.

What makes it different

commit-log toolsstandup-mr
Sourcelocal `git log`GitLab or GitHub API
Merge request stateready / blocked / draft / stale
Review queuepending only, approvals filtered out
Failed pipelineerror lines from the job trace or the Actions job log
Self-hosted (GitLab CE/EE, GitHub Enterprise)variesfirst class

Use

bash
npx standup-mr fetch                            # JSON, provider auto-detected
npx standup-mr fetch --provider github          # GitHub
npx standup-mr fetch --provider gitlab          # GitLab
npx standup-mr fetch --markdown                 # structured digest
npx standup-mr fetch --lang tr                  # Turkish date labels
bash
npx standup-mr fetch --markdown | npx standup-mr post --google-chat "$URL"

Identity

GitHubGitLab
Flags`--host` / `--token``--host` / `--token`
Env`GITHUB_HOST` / `GITHUB_TOKEN``GITLAB_HOST` / `GITLAB_TOKEN`
CLI session`gh` auth config`glab` auth config

GitHub defaults to `github.com` when no host is given. GitLab has no default —

self-hosted is the norm there, so a host must come from a flag, env var, or

`glab`'s own config.

The provider itself is picked in this order:

1. `--provider github` / `--provider gitlab`, if passed

2. a recognizable `--host` (`github.com`, `gitlab.com`, or a hostname

containing `github`/`gitlab`)

3. `STANDUP_PROVIDER`, or whichever of the `GITHUB_*` / `GITLAB_*` env pairs

is set

4. whichever of `gh` / `glab` is logged in

If none of these resolve — or both do, ambiguously — the command fails with a

clear error instead of guessing.

So if you already use `gh` or `glab`, there is nothing to configure.

Post it to chat

bash
npx standup-mr fetch --markdown | npx standup-mr post --slack "$SLACK_WEBHOOK_URL"

The three surfaces

CLI — the core. Emits JSON; zero runtime dependencies.

MCP server (`mcp/`) — one tool, `get_standup_data`, for Claude Desktop,

Cursor, or any MCP client. See `mcp/README.md`.

Claude Code plugin — the note-writing playbook, shipped as the `standup`

skill. From inside Claude Code:

code
/plugin marketplace add Jubstaaa/standup-mr
/plugin install standup@standup-mr

Then type `/standup`. Updates come with `/plugin marketplace update standup-mr`.

Using it from Cursor, Codex, or another assistant

If you're not using Claude Code, wire up the MCP server for live data and

paste in the note-writing rules separately.

Cursor — add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json`

(project-local):

json
{
    "mcpServers": {
        "standup": {
            "command": "npx",
            "args": ["-y", "standup-mr", "mcp"],
            "env": {
                "GITHUB_TOKEN": "ghp_..."
            }
        }
    }
}

Codex — add to `~/.codex/config.toml`:

toml
[mcp_servers.standup]
command = "npx"
args = ["-y", "standup-mr", "mcp"]

[mcp_servers.standup.env]
GITHUB_TOKEN = "ghp_..."

The exact config key and file path are version-dependent for both clients —

if a snippet above doesn't work, check [Cursor's MCP

docs](https://docs.cursor.com/context/mcp) or Codex's own config

documentation for the current format rather than trusting this file blindly.

The server exposes three tools:

ToolWhat it does
`get_standup_data`Reads the provider and returns the report as JSON. Optional `provider`, `host`, `lang`.
`get_note_instructions`Returns the note-writing rules, so the assistant can write the note the way the skill would.
`post_standup_note`Posts a finished note to a Slack, Discord or Google Chat webhook.

`post_standup_note` reads the webhook URL from `STANDUP_WEBHOOK_URL` and never

takes it as an argument — anyone holding that URL can post to the channel, so

it belongs with the tokens, not in a transcript. The payload shape is inferred

from the URL host; `kind` is only needed when a proxy hides it.

Three shapes are implemented: `slack` and `google-chat` both post `{"text"}`,

`discord` posts `{"content"}`.

Slack and Google Chat do not render standard Markdown, so the note is rewritten

on the way out: `bold` becomes `*bold*` and a `##` heading becomes a bold

line. Inline code, fenced blocks and their contents are left alone. Discord

speaks Markdown natively and is sent untouched. Anything else that accepts a Slack-shaped body —

Mattermost, Rocket.Chat, an n8n or Zapier endpoint — works today by passing

`kind: "slack"`, or `--slack URL` on the CLI.

Outside MCP, the same rules are available on stdout:

bash
npx standup-mr instructions >> AGENTS.md

`--markdown` is a digest, not a written note

`--markdown` organizes the raw material into readable sections. It does not

group events into themes or diagnose blockers — that is the model's work, and it

lives in the MCP client's prompt or in the Claude Code skill.

  • Without AI: a structured digest.
  • With AI: a note you can read out.

What the digest looks like

Anonymised output from a real Monday run — note that Friday and Saturday each

get their own section, and that a merge request GitLab has not evaluated is not

called ready:

markdown
# Monday, 31 August — dev

_Structured digest — not a written note._

## Previous working day: Friday, 28 August

- `acme/ui` pushed to — fix(keyboard): scale keys to viewport (4 commits)
- `acme/ui` accepted — chore(deps): bump @acme/ui to 0.5.18
- `acme/api` opened — feat: package subscription sales

## Previous working day: Saturday, 29 August

- `acme/ui` pushed to — fix(keyboard): close the autofill bar (1 commit)

## Ready to merge (2)

- `acme/api` !196 fix: normalise the +90 trunk prefix
- `acme/web` !194 refactor: loading state — **no pipeline ran**

## Blocked (1)

- `acme/terminal` !49 fix: relative date chips — **1 unresolved comment(s)**

## Reviews (2 pending)

- `acme/mobile` !501 chore: upgrade to RN 0.87 — Teammate

## Blockers

- `acme/mobile` !6 — job `quality`
    - `npm ERR! code E404`
    - `npm ERR! 404 Not Found - GET https://registry.example.com/@acme%2fui`

The last section is the point of the tool. Every other standup tool can tell you

that pipeline is red; this one opens the failed job's log and shows you the

404 — and a 404 rather than a 403 usually means the token's scope is wrong, not

that the package is missing.

Known limits

  • GitHub's events feed is shallow. It is capped at roughly 300 events over

the last 90 days, so a very active account or an old gap can silently lose

the earliest events. GitLab has no comparable documented cap.

  • **GitHub activity is only visible to a token belonging to that same

account**, and private-repository events do not show up for anyone else's

token, even with otherwise sufficient scopes.

  • On GitHub, CI that reports only through the legacy commit-statuses API

— still how some vendors integrate — shows up as `pipelineMissing`. Check

state is read from check-runs only.

  • A blocker whose diagnosis could not be fetched is still reported, as

`job: "unknown"` with a `diagnosis unavailable: …` error line. The merge

request is blocked either way; only the explanation is missing. Server

errors are retried twice first, and a rejected token still fails the run.

Upgrading from 0.1.x

0.2.0 changes the JSON output, the library API, and the MCP options. If you

pipe `standup fetch` into anything, or import the package, read

`CHANGELOG.md` before upgrading. The short version:

  • `previous` and `previousEvents` are replaced by `previousDays[]`, one entry

per active day, so a weekend no longer swallows Friday. `jq .previous` now

returns `null` with no error.

  • `MergeRequest`, `Review` and `Blocker` carry a required `provider` field, and

`Provider.getReviews` takes an `Identity` rather than a numeric id.

  • The MCP `CollectOptions.provider` is now a provider _name_; inject a

`Provider` instance through `providerImpl`.

Claude Code plugin users should run `/plugin marketplace update standup-mr` —

the `standup` skill changed along with the report shape.

Requirements

Node 20 or newer. The CLI core (`fetch`, `post`, `instructions`) pulls no

runtime dependencies. The MCP server (`mcp` command) brings one:

`@modelcontextprotocol/sdk`.

License

MIT

Frequently asked questions

What is standup-mr?

standup-mr is Standup notes from merge request state, not commit logs. Reads GitLab or GitHub: what is ready, what is blocked, and why your pipeline is red.

How do I install standup-mr?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is standup-mr open source?

Yes — it is hosted on GitHub at https://github.com/Jubstaaa/standup-mr.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP