Running the black-box @hasmcp/mcp-spec-test conformance suite against opfor's MCP server (built from source per the README: npm install && npm run build --workspaces --if-present then node runners/mcp/dist/index.js) shows the server printing a plaintext startup banner to stdout before any JSON-RPC traffic — specifically ◇ injected env (0) from .env // tip: ⌘ enable debugging { debug: true } — which corrupts the stdio JSON-RPC framing that MCP clients expect on that stream. As a result, the process gets torn down before the handshake completes ("server exited"), the official-SDK client sees the connection close, and 22 further checks can't be verified. This is a genuine framing bug rather than a test-environment artifact: on stdio transport, MCP servers must not write anything but JSON-RPC messages to stdout, and this banner (presumably a startup-logging/env-loader library) is doing exactly that.
Conformance report
MCP 2026-07-28 conformance report
Verdict: not conformant — 10 requirements violated.
|
|
| Target |
sh -c '[ -d agent-opfor ] || git clone https://github.com/KeyValueSoftwareSystems/agent-opfor && cd agent-opfor && npm install && npm run build --workspaces --if-present && node runners/mcp/dist/index.js' |
| Transport |
stdio |
| Revision tested |
2026-07-28 |
| Revisions supported |
2026-07-28, 2025-11-25 |
| Passed |
4 |
| Failed |
10 |
| Not verified |
22 |
| Cases applied |
36 |
| Duration |
21347ms |
| Generated |
2026-08-24T14:16:27.016Z |
| Tool |
@hasmcp/mcp-spec-test 0.1.1 |
Failed (10)
the server deviates from the spec here
server/discover
-
server/discover is answered without a session or handshake
expected 200, got 0: {"_raw":"server exited"}
0 !== 200
-
server/discover advertises the versions the server can serve
Cannot read properties of undefined (reading 'supportedVersions')
-
server/discover is a CacheableResult with usable cache hints
Cannot read properties of undefined (reading 'ttlMs')
-
server/discover reports server identity and capabilities
Cannot read properties of undefined (reading 'capabilities')
-
server/discover is stable across calls within its own TTL
Cannot read properties of undefined (reading 'supportedVersions')
-
server/discover advertises a revision this suite supports
Cannot read properties of undefined (reading 'supportedVersions')
Version negotiation
Official SDK interop
- a stock official-SDK client completes the handshake
MCP error -32000: Connection closed
- the handshake settles on a revision inside the supported window
initialize must return a protocolVersion, got undefined
- a stock official-SDK client can list tools
MCP error -32000: Connection closed
Not verified (22)
skipped; a skip is not a pass
Capability methods
- tools/list returns schema-conformant tools
cannot determine what the target supports — server/discover returned no result (status 0)
- tools/call on an unknown tool is an error, not a crash
cannot determine what the target supports — server/discover returned no result (status 0)
- tools/call returns a schema-conformant CallToolResult
cannot determine what the target supports — server/discover returned no result (status 0)
- prompts/list returns schema-conformant prompts
cannot determine what the target supports — server/discover returned no result (status 0)
- prompts/get returns messages with a role and content
cannot determine what the target supports — server/discover returned no result (status 0)
- resources/list returns schema-conformant resources
cannot determine what the target supports — server/discover returned no result (status 0)
- resources/templates/list returns schema-conformant templates
cannot determine what the target supports — server/discover returned no result (status 0)
- resources/read returns contents for every sampled resource
cannot determine what the target supports — server/discover returned no result (status 0)
- resources/read on an unknown uri is an error
cannot determine what the target supports — server/discover returned no result (status 0)
- following nextCursor terminates and does not repeat a page
cannot determine what the target supports — server/discover returned no result (status 0)
- an invalid pagination cursor is rejected (SHOULD)
cannot determine what the target supports — server/discover returned no result (status 0)
Version negotiation
- a version declared in _meta is accepted
cannot determine what the target supports — server/discover returned no result (status 0)
- an unsupported version is rejected with the supported list
cannot determine what the target supports — server/discover returned no result (status 0)
- clientInfo is optional (SHOULD, not MUST)
cannot determine what the target supports — server/discover returned no result (status 0)
Result envelope
- every result carries the required resultType
cannot determine what the target supports — server/discover returned no result (status 0)
- cacheable list results carry the schema-required cache hints
cannot determine what the target supports — server/discover returned no result (status 0)
- results identify the server in _meta
cannot determine what the target supports — server/discover returned no result (status 0)
- a client on an older version receives no newer-revision fields
cannot determine what the target supports — server/discover returned no result (status 0)
subscriptions/listen
- subscriptions/listen acknowledges only the opted-in notification types
cannot determine what the target supports — server/discover returned no result (status 0)
- the acknowledgment carries the subscription id for correlation
cannot determine what the target supports — server/discover returned no result (status 0)
- a listen requesting no notification types is not a subscription to everything
cannot determine what the target supports — server/discover returned no result (status 0)
- a cancelled subscription ends with a conformant teardown result, if it sends one
cannot determine what the target supports — server/discover returned no result (status 0)
Passed (4)
checked and conformant
server/discover
- the suite is reading a schema that matches the features it selected
Result envelope
- schema sanity: the envelope fields match the features selected
Official SDK interop
- the official SDK does not yet implement the newest revision
subscriptions/listen
- schema sanity: SubscriptionsListenResult requires _meta and resultType
How to reproduce
With Docker:
docker pull hasmcp/mcp-spec-test:latest
docker run --rm hasmcp/mcp-spec-test -c "sh -c '[ -d agent-opfor ] || git clone https://github.com/KeyValueSoftwareSystems/agent-opfor && cd agent-opfor && npm install && npm run build --workspaces --if-present && node runners/mcp/dist/index.js'" --spec-version 2026-07-28
(on Apple Silicon / arm64 hosts, add --platform linux/amd64; the published image currently only ships an amd64 manifest but runs fine under emulation)
Without Docker (npx):
npx @hasmcp/mcp-spec-test@latest -c "sh -c '[ -d agent-opfor ] || git clone https://github.com/KeyValueSoftwareSystems/agent-opfor && cd agent-opfor && npm install && npm run build --workspaces --if-present && node runners/mcp/dist/index.js'" --spec-version 2026-07-28
You can see the offending stdout line directly with:
node runners/mcp/dist/index.js
# stdout prints: ◇ injected env (0) from .env // tip: ⌘ enable debugging { debug: true }
This report was generated by an automated MCP conformance sweep across public MCP server repos. If this turns out to be a false positive specific to the test container/environment, or not applicable, feel free to close it — no offense taken.
Running the black-box
@hasmcp/mcp-spec-testconformance suite againstopfor's MCP server (built from source per the README:npm install && npm run build --workspaces --if-presentthennode runners/mcp/dist/index.js) shows the server printing a plaintext startup banner to stdout before any JSON-RPC traffic — specifically◇ injected env (0) from .env // tip: ⌘ enable debugging { debug: true }— which corrupts the stdio JSON-RPC framing that MCP clients expect on that stream. As a result, the process gets torn down before the handshake completes ("server exited"), the official-SDK client sees the connection close, and 22 further checks can't be verified. This is a genuine framing bug rather than a test-environment artifact: on stdio transport, MCP servers must not write anything but JSON-RPC messages to stdout, and this banner (presumably a startup-logging/env-loader library) is doing exactly that.Conformance report
MCP 2026-07-28 conformance report
Verdict: not conformant — 10 requirements violated.
sh -c '[ -d agent-opfor ] || git clone https://github.com/KeyValueSoftwareSystems/agent-opfor && cd agent-opfor && npm install && npm run build --workspaces --if-present && node runners/mcp/dist/index.js'Failed (10)
the server deviates from the spec here
server/discover
server/discover is answered without a session or handshake
expected 200, got 0: {"_raw":"server exited"}
0 !== 200
server/discover advertises the versions the server can serve
Cannot read properties of undefined (reading 'supportedVersions')
server/discover is a CacheableResult with usable cache hints
Cannot read properties of undefined (reading 'ttlMs')
server/discover reports server identity and capabilities
Cannot read properties of undefined (reading 'capabilities')
server/discover is stable across calls within its own TTL
Cannot read properties of undefined (reading 'supportedVersions')
server/discover advertises a revision this suite supports
Cannot read properties of undefined (reading 'supportedVersions')
Version negotiation
a request with no version at all is served on the default
a version-less request must be served, got 0: {"_raw":"server exited"}
0 !== 200
Official SDK interop
MCP error -32000: Connection closed
initialize must return a protocolVersion, got undefined
MCP error -32000: Connection closed
Not verified (22)
skipped; a skip is not a pass
Capability methods
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
Version negotiation
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
Result envelope
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
subscriptions/listen
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
cannot determine what the target supports — server/discover returned no result (status 0)
Passed (4)
checked and conformant
server/discover
Result envelope
Official SDK interop
subscriptions/listen
How to reproduce
With Docker:
(on Apple Silicon / arm64 hosts, add
--platform linux/amd64; the published image currently only ships an amd64 manifest but runs fine under emulation)Without Docker (npx):
You can see the offending stdout line directly with:
This report was generated by an automated MCP conformance sweep across public MCP server repos. If this turns out to be a false positive specific to the test container/environment, or not applicable, feel free to close it — no offense taken.