AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Mcp Server Diff

mcp-sammorrowdrums-mcp-server-diff · by SamMorrowDrums

A reusable GitHub Actions workflow for testing MCP server conformance between versions

No reviews yet
0 installs
17 views
0.0% view→install

Install

$ agentstack add mcp-sammorrowdrums-mcp-server-diff

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-sammorrowdrums-mcp-server-diff)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mcp Server Diff? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

MCP Server Diff

[](https://github.com/marketplace/actions/mcp-server-diff) [](https://www.npmjs.com/package/mcp-server-diff) [](https://github.com/SamMorrowDrums/mcp-server-diff/releases) [](https://opensource.org/licenses/MIT)

A GitHub Action for diffing Model Context Protocol (MCP) server public interfaces between versions. Compares the current branch against a baseline to surface any changes to your server's exposed tools, resources, prompts, and capabilities.

> Also available as a standalone CLI — see [CLI Documentation](#cli-tool) or install with npx mcp-server-diff

Overview

MCP servers expose a public interface to AI assistants: tools (with their input schemas), resources, prompts, and server capabilities. As your server evolves, changes to this interface are worth tracking. This action automates public interface comparison by:

  1. Building your MCP server from both the current branch and a baseline (merge-base, tag, or specified ref)
  2. Querying both versions for their complete public interface (tools, resources, prompts, capabilities)
  3. Generating a diff report showing exactly what changed
  4. Surfacing results directly in GitHub's Job Summary

This is not about testing internal logic or correctness—it's about visibility into what your server advertises to clients.

Quick Start

Create .github/workflows/mcp-diff.yml in your repository:

name: MCP Server Diff

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
    tags: ['v*']

permissions:
  contents: read

jobs:
  mcp-diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: SamMorrowDrums/mcp-server-diff@v2
        with:
          setup_node: true
          install_command: npm ci
          build_command: npm run build
          start_command: node dist/stdio.js

Language Examples

Node.js / TypeScript

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_node: true
    node_version: '22'
    install_command: npm ci
    build_command: npm run build
    start_command: node dist/stdio.js

Python

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_python: true
    python_version: '3.12'
    install_command: pip install -e .
    start_command: python -m my_mcp_server

Go

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_go: true
    install_command: go mod download
    build_command: go build -o bin/server ./cmd/stdio
    start_command: ./bin/server

Rust

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_rust: true
    install_command: cargo fetch
    build_command: cargo build --release
    start_command: ./target/release/my-mcp-server

C# / .NET

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_dotnet: true
    dotnet_version: '9.0.x'
    install_command: dotnet restore
    build_command: dotnet build -c Release
    start_command: dotnet run --no-build -c Release

Custom Setup

If you need more control over environment setup (caching, specific registries, etc.), do your own setup before calling the action:

steps:
  - uses: actions/checkout@v4
    with:
      fetch-depth: 0

  - uses: actions/setup-node@v4
    with:
      node-version: '22'
      cache: 'npm'
      registry-url: 'https://npm.pkg.github.com'

  - uses: SamMorrowDrums/mcp-server-diff@v2
    with:
      install_command: npm ci
      build_command: npm run build
      start_command: node dist/stdio.js

Testing Multiple Transports

Test both stdio and HTTP transports in a single run using the configurations input:

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_node: true
    install_command: npm ci
    build_command: npm run build
    configurations: |
      [
        {
          "name": "stdio",
          "transport": "stdio",
          "start_command": "node dist/stdio.js"
        },
        {
          "name": "streamable-http",
          "transport": "streamable-http",
          "start_command": "node dist/http.js",
          "server_url": "http://localhost:3000/mcp"
        }
      ]

Inputs Reference

Language Setup (Optional)

| Input | Description | Default | |-------|-------------|---------| | setup_node | Set up Node.js environment | false | | node_version | Node.js version | 20 | | setup_python | Set up Python environment | false | | python_version | Python version | 3.11 | | setup_go | Set up Go environment | false | | go_version | Go version (reads from go.mod if empty) | "" | | setup_rust | Set up Rust environment | false | | rust_toolchain | Rust toolchain | stable | | setup_dotnet | Set up .NET environment | false | | dotnet_version | .NET version | 8.0.x |

Required Inputs

| Input | Description | |-------|-------------| | install_command | Command to install dependencies (e.g., npm ci, pip install -e ., go mod download) |

Server Configuration

| Input | Description | Default | |-------|-------------|---------| | build_command | Command to build the server. Optional for interpreted languages. | "" | | start_command | Command to start the server for stdio transport | "" | | transport | Transport type: stdio or streamable-http | stdio | | server_url | Server URL for HTTP transport (e.g., http://localhost:3000/mcp) | "" | | configurations | JSON array of test configurations for testing multiple transports | "" | | server_timeout | Timeout in seconds to wait for server response | 10 | | env_vars | Environment variables as newline-separated KEY=VALUE pairs | "" |

Either start_command (for stdio) or server_url (for HTTP) must be provided, unless using configurations.

Comparison Configuration

| Input | Description | Default | |-------|-------------|---------| | compare_ref | Git ref to compare against. Auto-detects merge-base on PRs or previous tag on tag pushes if not specified. | "" | | fail_on_diff | Fail the action if API changes are detected. Useful for release validation workflows. | false | | fail_on_error | Fail the action if a genuine probe error occurs (e.g. the server fails to start on both sides). A configuration that starts on only one side is reported as "missing on one side" and is not treated as a probe error — see [One-Sided Startup Failures](#one-sided-startup-failures). | true |

Configuration Object Schema

When using configurations, each object supports:

| Field | Description | Required | |-------|-------------|----------| | name | Identifier for this configuration (appears in report) | Yes | | transport | stdio or streamable-http | No (default: stdio) | | start_command | Server start command (stdio: spawns process, HTTP: starts server in background) | Yes for stdio, optional for HTTP | | server_url | URL for HTTP transport | Required for streamable-http | | startup_wait_ms | Milliseconds to wait for HTTP server to start (when using start_command) | No (default: 2000) | | pre_test_command | Command to run before probing (alternative to start_command for HTTP) | No | | pre_test_wait_ms | Milliseconds to wait after pre_test_command | No | | post_test_command | Command to run after probing (cleanup, used with pre_test_command) | No | | headers | HTTP headers for this configuration | No | | env_vars | Additional environment variables | No | | custom_messages | Config-specific custom messages | No | | base_start_command | Command for baseline comparison (skips git checkout for this config) | No | | base_server_url | URL for baseline HTTP server (used with base_start_command) | No |

Comparing Against External Servers

When comparing against external servers (e.g., Docker images, remote services), use base_start_command to specify a different command for the baseline. This skips git checkout for that configuration and probes the specified server directly:

configurations: |
  [
    {
      "name": "compare-versions",
      "transport": "stdio",
      "start_command": "docker run -i ghcr.io/example/mcp-server:v2.0.0",
      "base_start_command": "docker run -i ghcr.io/example/mcp-server:v1.0.0"
    }
  ]

This is useful for:

  • Version comparison: Compare a new release against the previous version
  • Golden reference testing: Compare your local code against a known-good reference
  • Cross-implementation testing: Compare different implementations of the same server
  • Self-testing CI: Verify the action detects diffs by comparing two known-different servers

For HTTP transport, use base_server_url alongside base_start_command:

configurations: |
  [
    {
      "name": "http-comparison",
      "transport": "streamable-http",
      "start_command": "docker run -p 3000:3000 myserver:latest",
      "server_url": "http://localhost:3000/mcp",
      "base_start_command": "docker run -p 3001:3000 myserver:v1.0.0",
      "base_server_url": "http://localhost:3001/mcp"
    }
  ]

How It Works

Execution Flow

  1. Baseline Detection: Determines the comparison ref:
  • For pull requests: merge-base with target branch
  • For tag pushes: previous tag (e.g., v1.1.0 compares against v1.0.0)
  • Explicit: uses compare_ref if provided
  1. Build Baseline: Creates a git worktree at the baseline ref and builds the server
  2. Build Current: Builds the server from the current branch
  3. Conformance Testing: Sends MCP protocol requests to both servers:
  • initialize - Server capabilities and metadata
  • tools/list - Available tools and their schemas
  • resources/list - Available resources
  • prompts/list - Available prompts
  1. Report Generation: Produces a Markdown report with diffs, uploaded as an artifact and displayed in Job Summary

What Gets Compared

The action queries the public interface of both server versions and compares the responses:

| Method | What It Reveals | |--------|----------------| | initialize | Server name, version, capabilities | | tools/list | Available tools and their JSON schemas | | resources/list | Exposed resources | | prompts/list | Available prompts |

Differences appear as unified diffs in the report. Common changes include:

  • New tools, resources, or prompts added
  • Schema changes (new parameters, updated descriptions)
  • Capability changes (new features enabled)
  • Version string updates

One-Sided Startup Failures

Sometimes a configuration starts on one side of the comparison but fails to start on the other. The most common cause is a brand-new configuration that depends on a CLI flag or option that doesn't exist on the compare ref yet — for example a PR that introduces a new scoped server mode. On the compare ref the unknown flag is rejected and the server exits with something like MCP error -32000: Connection closed.

When exactly one side fails to start (and the other probes successfully), the action:

  1. Reports a fail on the side that could not start, naming the version (current

branch or compare ref) in a dedicated "🚫 missing on one side" section and a per-config callout, instead of an opaque probe error.

  1. Diffs the working side against an empty baseline, so the entire surface of the

new (or removed) configuration renders as added/removed — giving you a complete picture of what it exposes.

  1. Does not trip fail_on_error. A one-sided startup failure is treated as a

surface difference (config-missing), not a genuine probe error, so an introducing PR isn't failed for the expected "this config doesn't exist on the base ref yet" case. It still counts as a difference, so fail_on_diff will flag it if enabled.

When both sides fail to start, that is a genuine probe failure: it is reported as an error and trips fail_on_error (when enabled).

Transport Support

stdio Transport

The default transport communicates with your server via stdin/stdout using JSON-RPC. For stdio, each configuration spawns a fresh server process:

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_node: true
    install_command: npm ci
    build_command: npm run build
    start_command: node dist/stdio.js

Streamable HTTP Transport

For HTTP servers, you typically want to start the server once and test multiple configurations against it. Use start_command at the configuration level—the action spawns the server, waits for startup, probes it, then terminates it after that configuration completes:

configurations: |
  [{
    "name": "http-server",
    "transport": "streamable-http",
    "start_command": "node dist/http.js",
    "server_url": "http://localhost:3000/mcp",
    "startup_wait_ms": 2000
  }]

Per-configuration server lifecycle: If your use case requires a fresh server instance per configuration (e.g., testing different flags or environment variables), include start_command in each configuration—each will get its own server process started and stopped.

Shared server for multiple configurations: If you want one HTTP server to handle multiple test configurations, use pre_test_command/post_test_command on the first/last configuration, or start the server in a prior workflow step:

configurations: |
  [
    {
      "name": "config-a",
      "transport": "streamable-http",
      "server_url": "http://localhost:3000/mcp",
      "pre_test_command": "node dist/http.js &",
      "pre_test_wait_ms": 2000
    },
    {
      "name": "config-b",
      "transport": "streamable-http",
      "server_url": "http://localhost:3000/mcp"
    },
    {
      "name": "config-c",
      "transport": "streamable-http",
      "server_url": "http://localhost:3000/mcp",
      "post_test_command": "pkill -f 'node dist/http.js' || true"
    }
  ]

Pre-deployed servers: For already-running servers (staging, production), omit lifecycle commands entirely:

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    install_command: 'true'
    transport: streamable-http
    server_url: https://mcp.example.com/api

Version Comparison Strategies

Pull Requests

On pull requests, the action automatically compares against the merge-base with the target branch. This shows exactly what changes the PR introduces.

Tag Releases

When triggered by a tag push matching v*, the action finds the previous tag and compares against it:

on:
  push:
    tags: ['v*']

# v1.2.0 will automatically compare against v1.1.0

Explicit Baseline

Specify any git ref to compare against:

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_node: true
    install_command: npm ci
    build_command: npm run build
    start_command: node dist/stdio.js
    compare_ref: v1.0.0

Failing on Changes (Release Validation)

For release workflows where you want to ensure no API changes, use fail_on_diff:

- uses: SamMorrowDrums/mcp-server-diff@v2
  with:
    setup_node: true
    install_command: npm ci
    build_command: npm run build
    start_command: node dist/stdio.js
    compare_ref: v1.0.0
    fail_on_diff: true  # Action fails if any API changes are detected

Artifacts and Reports

The action produces:

  1. Job Summary: Inline Markdown report in the GitHub Actions UI showing test results and diffs
  2. Artifact: mcp-diff-report artifact containing MCP_DIFF_REPORT.md for download or further processing

Example Output

No Changes Detected

When the MCP server's public interface hasn't changed between branches:

📊 Comparison:
  Current: HEAD
  Compare: abc1234 (v1.0.0)

🧪 Running diff...

📊 Phase 3: Comparing results...
📋 Configuration stdio: ✅ No changes

✅ No API Changes - All configurations match the baseline.

Changes Detected

When changes are

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.