mcptest docs GitHub

Scenario 6: URL target against staging

You have an MCP server deployed to a staging environment. It is behind a bearer token, it routes by tenant header, and it can take a few seconds to wake up after a deploy. You want one YAML that runs the same suite locally (against a stdio binary) and in CI (against the staging URL), with credentials picked up from the environment.

The trick is to keep the same tools: block and swap only the servers: entry between runs. Two ways to do that: two named servers in one file picked by --server, or one server overridden via CLI flags. Both work; pick by team preference.

The YAML

Save this as tests/staging.yml:

# yaml-language-server: $schema=https://mcptest.sh/schema/v1.json

servers:
  local:
    command: ["./target/debug/my-mcp-server"]

  staging:
    url: "https://mcp.staging.example.com/v1"
    auth:
      bearer_token_env: "MCPTEST_STAGING_TOKEN"
    headers:
      X-Tenant:
        env: MCPTEST_STAGING_TENANT
      X-Trace-Id: "${run_id}"
    wait_for_ready: "https://mcp.staging.example.com/healthz"
    http:
      timeout: 30s
      connect_timeout: 5s

variables:
  run_id:
    from_env: "GITHUB_RUN_ID"
    default: "local-dev"

tools:
  - name: "lookup happy path"
    server: staging
    tool: "lookup_record"
    args:
      id: "rec_abc123"
    expect:
      - target: "result.content[0].text"
        matcher:
          contains: "rec_abc123"

  - name: "lookup error path"
    server: staging
    tool: "lookup_record"
    args:
      id: "rec_missing"
    expect:
      - target: "result.isError"
        matcher:
          exact: true

What is happening here:

Local invocation

To run against the local binary instead of staging, override the server with the CLI:

mcptest run --server-command "./target/debug/my-mcp-server" tests/staging.yml

The --server-command flag overrides the command of every server in the suite with the supplied stdio command, so the tool tests now run against your local binary without you editing the YAML. The argument is split with POSIX shell rules, so --server-command "./dev-server --debug" parses to two argv elements.

Alternatively, point the suite at a different URL endpoint:

mcptest run --server-url "http://localhost:8080/v1" tests/staging.yml

The --server-url flag overrides the url of every server in the suite. It is mutually exclusive with --server-command.

CI invocation

# .github/workflows/staging.yml
name: staging integration
on:
  schedule:
    - cron: "0 */4 * * *"   # every four hours
  workflow_dispatch:

jobs:
  staging:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - run: cargo install mcptest --locked
      - run: mcptest run tests/staging.yml
        env:
          MCPTEST_STAGING_TOKEN: ${{ secrets.MCPTEST_STAGING_TOKEN }}
          MCPTEST_STAGING_TENANT: "acme"

Two GitHub Actions secrets are referenced: the bearer token and the tenant slug. Both are read into env vars before mcptest run. The runner picks them up automatically.

Expected output

mcptest run tests/staging.yml

  WAIT  staging -> https://mcp.staging.example.com/healthz   (ready in 2.1s)
  PASS  lookup happy path                                    (412ms)
  PASS  lookup error path                                    (387ms)

2 passed, 0 failed in 3.0s (1 readiness probe)

The WAIT line shows the readiness probe; the per-test lines show the actual request time. If the readiness probe fails (server never becomes ready in the configured window), the run aborts with a structured error before any test runs.

Troubleshooting

See also