mcpfixture

command
v0.48.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Command mcpfixture is a deterministic MCP upstream fixture for the release QA gate (Spec 081, FR-006/FR-007). One binary serves the same two tools over three transports so gate matrix cells never depend on third-party services:

mcpfixture --transport stdio                     # newline-delimited JSON-RPC on stdin/stdout
mcpfixture --transport http --port 18080         # streamable-http at http://127.0.0.1:18080/mcp
mcpfixture --transport sse  --port 18081         # legacy SSE at http://127.0.0.1:18081/sse (+ POST /message)

Transports are served by mark3labs/mcp-go's server package — the same library whose CLIENT side mcpproxy pins (internal/upstream/core uses transport.CreateSSEClient / NewStreamableHTTP / NewStdio), so the wire contract is protocol-correct by construction instead of hand-rolled:

  • sse: GET /sse opens the event stream and announces the message endpoint ("endpoint" event, relative URL resolved against the client's base URL); requests are POSTed to /message?sessionId=… and responses stream back as SSE "message" events.
  • http: POST /mcp single-shot JSON responses (StreamableHTTPServer).
  • stdio: newline-delimited JSON-RPC frames (StdioServer).

Tools (deterministic, FR-007c):

  • echo — returns the call arguments back as JSON text: {"echo": {...arguments...}}
  • ping — returns {"message":"pong","counter":N,"instance_id":"…"}; the counter increases monotonically per process and the instance_id is random per process start, so kill/restart tests (FR-007d) can prove the reconnected upstream is a NEW instance (counter reset, new id).

SIGTERM/SIGINT exits cleanly with code 0 on every transport (docker stop sends SIGTERM to PID 1, and the gate kills fixtures between matrix steps).

Docker cell (FR-009) argv composition, verified against internal/upstream/core/isolation.go + connection_docker.go:

server config: command="/mcpfixture", args=["--transport","stdio"],
               isolation.image="mcpfixture:gate"
DetectRuntimeType(filepath.Base("/mcpfixture")) → "binary" (default case)
TransformCommandForContainer(binary) → command+args passed through unchanged
GetDockerImage → buildFullImageName("mcpfixture:gate") → "docker.io/library/mcpfixture:gate"
  (no slash ⇒ registry+library prefix; Docker normalizes local short tags
   the same way, so a locally built `mcpfixture:gate` resolves without a pull)
final argv: docker run --rm -i --name mcpproxy-<server>-<rand> <labels>
            [--log-opt …] [--network <mode>] [limits] [-e K=V …]
            docker.io/library/mcpfixture:gate /mcpfixture --transport stdio

Because the container command is always appended explicitly after the image, the image must NOT set an ENTRYPOINT (it would prefix the argv and break `/mcpfixture --transport stdio`); it ships CMD ["/mcpfixture","--transport","stdio"] as a default for bare `docker run` instead. See cmd/mcpfixture/Dockerfile and scripts/gate/build-fixture-image.sh.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL