Skip to main content
Glama

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 tools

standup-mr

Source

local git log

GitLab or GitHub API

Merge request state

ready / blocked / draft / stale

Review queue

pending only, approvals filtered out

Failed pipeline

error lines from the job trace or the Actions job log

Self-hosted (GitLab CE/EE, GitHub Enterprise)

varies

first class

Related MCP server: Git Insight MCP

Use

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
npx standup-mr fetch --markdown | npx standup-mr post --google-chat "$URL"

Identity

GitHub

GitLab

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

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:

/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):

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

Codex — add to ~/.codex/config.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 or Codex's own config documentation for the current format rather than trusting this file blindly.

The server exposes three tools:

Tool

What 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:

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:

# 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

Available Tools

3 tools
get_note_instructionsA

Returns the note-writing rules — the playbook for turning get_standup_data output into a standup note a person would actually say out loud: how to group the previous day by theme, how to derive today from open merge requests, and how to report a blocker from its job log. Read-only, no arguments, no network. Call it once before writing the first note; the rules do not change between calls.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does well: it discloses that the tool is read-only, takes no arguments, makes no network calls, and that the returned rules are static. This exceeds a minimal viable description, though it could add more detail about the exact structure of the returned instructions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense but every sentence earns its place: first sentence defines the core purpose and output, second states key behavioral constraints, third gives direct usage guidance. It is front-loaded with the most important information and has no filler or redundant repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters, no output schema, and simple read-only behavior, the description fully covers what an agent needs to invoke it correctly: what it returns (rules for writing standup notes), behavior (read-only, no network), and when to call it (once before first note). Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema provides no semantic information. The description explicitly states 'no arguments', which confirms the interface. Baseline for zero parameters is 4, and the description's explicit mention adds no extra parameter semantics beyond stating there are none.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns note-writing rules and explicitly ties them to transforming get_standup_data output into a speakable standup note. It distinguishes itself from sibling tools by describing its role in the pipeline (before writing the note), making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: call it once before writing the first note, and notes the rules do not change between calls. It does not explicitly mention when not to use it or alternative tools, but for a zero-argument read-only tool with no siblings that overlap, this is sufficient and not misleading.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_standup_dataA

Collect merge-request-based standup data from GitLab or GitHub. Returns one JSON object: today, previousDays[] with the events of each, todayEvents[], myMrs[] bucketed ready / blocked / draft / stale, reviews[] waiting on you, and blockers[] carrying the error lines read out of each failed pipeline job log.

Call it once at the start of a working day, to write a standup note. It is a snapshot, not a search API: it cannot fetch one named merge request, reach further back than the previous working day, or filter by project.

Read-only, and credentials never come from an argument — they come from the environment or a logged-in gh / glab session. A rejected token, a refused resource or a rate limit fails the call with the host's own message, after two retries on transient server errors. A blocker whose diagnosis could not be fetched is still returned, with job: "unknown", so a red pipeline is never silently dropped.

ParametersJSON Schema
NameRequiredDescriptionDefault
hostNoSelf-hosted host, without a scheme, e.g. gitlab.example.com or github.example.com. Required for GitLab, which has no default host; optional for GitHub, which defaults to github.com. A recognisable host also settles `provider` on its own, so the two are rarely both needed.
langNoLanguage for the date labels inside the returned JSON: en (default) or tr. It relabels dates and nothing else — no field is translated, and the standup note itself is written by the caller, in whatever language they are speaking.
providerNoWhich provider to read. Omit to auto-detect, in this order: a recognisable host, STANDUP_PROVIDER, a GITHUB_*/GITLAB_* environment pair, then whichever of the gh / glab CLIs is logged in. Pass it when both are configured — ambiguity fails the call rather than being guessed at.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so thoroughly. It discloses read-only nature, credential sourcing from environment or logged-in sessions, retry behavior on transient errors, error message propagation, and the handling of undiagnosable blockers with 'job: "unknown"'. These are non-obvious behavioral traits critical for an agent to invoke safely.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but every sentence serves a purpose: it front-loads the return structure, then states usage, then safety and error behavior. There is no filler or redundancy; the length is justified by the complexity of the tool's behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the absence of an output schema and sibling tools, the description compensates by fully specifying the return object's top-level fields, usage timing, limitations, authentication, and error cases. An agent has all necessary information to correctly decide when and how to call this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% coverage with detailed descriptions for all three parameters, including defaults and auto-detection rules. The description adds minor complementary context, such as the purpose of 'lang' and the relationship between host and provider, but the schema does the heavy lifting. A score of 4 reflects the schema's richness and the description's reinforcing value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function with a specific verb ('Collect') and resource ('merge-request-based standup data from GitLab or GitHub'), and outlines the exact shape of the returned JSON object. This is a precise, action-oriented description that leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'Call it once at the start of a working day, to write a standup note.' It also defines exclusions: 'It is a snapshot, not a search API: it cannot fetch one named merge request, reach further back than the previous working day, or filter by project.' This provides clear context and boundaries for usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

post_standup_noteA

Posts a finished standup note to a chat webhook. This one has a side effect: it sends a message other people will see, so only call it on a note the user has agreed to send.

The webhook URL is read from STANDUP_WEBHOOK_URL, never from an argument — a webhook URL is a credential, since anyone holding it can post to the channel. Slack and Discord payload shapes are supported; the shape is inferred from the URL host, and kind is only needed for a proxied or self-hosted endpoint whose host gives nothing away — Mattermost and Rocket.Chat take the slack shape. A missing URL, an unrecognised host, or a webhook that rejects the message comes back as an error rather than a silent success.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoWhich payload shape to send: slack and google-chat post {"text"}, discord posts {"content"}. Omit it — the shape is inferred from the webhook host. Pass it only when the host is not recognisable, e.g. a proxy in front of the real webhook.
textYesThe note to post, as the chat should render it. Slack and Discord both take Markdown, so send the written note rather than the raw JSON from get_standup_data.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full responsibility for behavioral disclosure. It clearly discloses the side effect (sends a visible message), the credential nature of the webhook URL, support for multiple payload shapes, and error handling (errors instead of silent success). This is thorough and goes well beyond basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it states the core action and side effect first, then covers credentials, payload shapes, and error behavior in a logical order. Every sentence provides necessary context with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema, the description covers usage, side effects, credential handling, supported formats, and error behavior. The only minor gap is the lack of a specific return value format on success, but that is not critical for this action-oriented tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage with rich descriptions for both parameters. The description adds extra value by explaining that 'text' should be the rendered Markdown note, not raw JSON, and reinforces when 'kind' is needed. This goes beyond the schema baseline without redundancy.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Posts a finished standup note to a chat webhook.' It clearly distinguishes this tool from sibling tools like get_standup_data and get_note_instructions by framing it as the posting action with a side effect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when not to call the tool ('only call it on a note the user has agreed to send') and clarifies when the 'kind' parameter is necessary (only for unrecognized hosts). It also warns that webhook URLs must come from environment variables, not arguments, which guides safe usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev0.4.3
    • Changedpost_standup_note2 fields changed
      • changedInput schema / properties / kind / description
        Previous value: -"Which payload shape to send: slack posts {\"text\"}, discord posts {\"content\"}. Omit it — the shape is inferred from the webhook host. Pass it only when the host is not recognisable, e.g. a proxy in front of the real webhook."New value: +"Which payload shape to send: slack and google-chat post {\"text\"}, discord posts {\"content\"}. Omit it — the shape is inferred from the webhook host. Pass it only when the host is not recognisable, e.g. a proxy in front of the real webhook."
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "slack",
        -  "discord"
        -]New value: +[
        +  "slack",
        +  "discord",
        +  "google-chat"
        +]
  2. 2 tool updatesv0.4.2
    • Addedget_note_instructions
    • Addedpost_standup_note
  3. 1 tool updatev0.4.1
    • Changedget_standup_data3 fields changed
      • changedInput schema / properties / host / description
        Previous value: -"Self-hosted host, without a scheme, e.g. gitlab.example.com or github.example.com. GitHub defaults to github.com; GitLab has no default, so self-hosted GitLab needs this or GITLAB_HOST."New value: +"Self-hosted host, without a scheme, e.g. gitlab.example.com or github.example.com. Required for GitLab, which has no default host; optional for GitHub, which defaults to github.com. A recognisable host also settles `provider` on its own, so the two are rarely both needed."
      • changedInput schema / properties / lang / description
        Previous value: -"Language for the date labels inside the returned JSON. Defaults to en. Only the labels change — the standup note itself is written by the caller."New value: +"Language for the date labels inside the returned JSON: en (default) or tr. It relabels dates and nothing else — no field is translated, and the standup note itself is written by the caller, in whatever language they are speaking."
      • changedInput schema / properties / provider / description
        Previous value: -"Which provider to read. Omit to auto-detect, in this order: a recognisable host, STANDUP_PROVIDER, a GITHUB_*/GITLAB_* environment pair, then whichever of the gh / glab CLIs is logged in."New value: +"Which provider to read. Omit to auto-detect, in this order: a recognisable host, STANDUP_PROVIDER, a GITHUB_*/GITLAB_* environment pair, then whichever of the gh / glab CLIs is logged in. Pass it when both are configured — ambiguity fails the call rather than being guessed at."
  4. 1 tool updatev0.1.1
    • Changedget_standup_data3 fields changed
      • addedInput schema / properties / host
        Added value: +{
        +  "description": "Self-hosted host, without a scheme, e.g. gitlab.example.com or github.example.com. GitHub defaults to github.com; GitLab has no default, so self-hosted GitLab needs this or GITLAB_HOST.",
        +  "type": "string"
        +}
      • addedInput schema / properties / lang
        Added value: +{
        +  "description": "Language for the date labels inside the returned JSON. Defaults to en. Only the labels change — the standup note itself is written by the caller.",
        +  "enum": [
        +    "en",
        +    "tr"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / provider
        Added value: +{
        +  "description": "Which provider to read. Omit to auto-detect, in this order: a recognisable host, STANDUP_PROVIDER, a GITHUB_*/GITLAB_* environment pair, then whichever of the gh / glab CLIs is logged in.",
        +  "enum": [
        +    "github",
        +    "gitlab"
        +  ],
        +  "type": "string"
        +}
  5. 1 tool updatev0.1.0
    • First observedget_standup_data

TDQS

A4.7/5.0
Disambiguation5/5

The three tools serve completely distinct purposes: fetching standup data, posting a note, and retrieving writing instructions. There is zero functional overlap and an agent can clearly select the correct tool for each step.

Naming Consistency5/5

All tools follow the consistent verb_noun pattern (get_, post_, get_), and each name clearly communicates its action and subject. The naming style is uniform and predictable.

Tool Count5/5

With exactly three tools, the server is tightly scoped to the standup workflow. Each tool is necessary for the core flow: obtaining data, getting instructions, and posting the note. No redundant tools exist.

Completeness5/5

The tool set covers the entire standup lifecycle: data collection, note authoring rules, and publishing. The description explicitly notes limitations but within its stated scope, there are no missing operations that would break an agent's workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jubstaaa/standup-mr'

If you have feedback or need assistance with the MCP directory API, please join our Discord server