mcp_probe 0.9.1
mcp_probe: ^0.9.1 copied to clipboard
Conformance checks and a test harness for Model Context Protocol (MCP) servers. Runs any MCP server over stdio and asserts on its behavior from package:test. Built on dart_mcp.
0.9.1 #
-
Declare the platforms the harness can actually run on. The pubspec carried no
platforms:block, so pub.dev inferred the full set and advertised iOS. The harness starts the server under test withProcess.start, which iOS refuses outright: built against an iPhone 17 Pro simulator on iOS 26.5, the run raisedProcessException: Starting new processes is not supported on iOSfromMcpServerHarness.start. Android, Linux, macOS and Windows are now declared and iOS is not; web is excluded too, having nodart:io. Android was checked on a live arm64 Android 15 image with SELinux enforcing, where the handshake and the conformance rules pass. -
Name a repeated pagination cursor instead of only reporting that the page count ran out. A server that hands back the cursor it was given is not paginating, it is ignoring the parameter — the usual shape of a server that wires up
nextCursorwithout implementing it. The 10000-page backstop caught the symptom and reported "did not terminate after 10000 pages"; the report now says which cursor repeated and that the server is not advancing. For a tool whose product is the diagnosis, the difference is the whole point. The backstop stays for a server that keeps minting fresh cursors.
0.9.0 #
- Fix the version this harness reports to servers.
harnessVersionwas still0.1.0— it had not moved through seven releases — and it is what every server sees as the connecting client's version, and what a conformance report names. Anyone reading their server logs to see which client probed them got the wrong answer. It now tracks the package version, and a test compares the two so it cannot drift again: nothing had ever compared that constant to anything, which is why it went stale silently.
0.8.0 #
-
Fix an unhandled async error that could take down the caller's isolate. When a server process exits immediately — a wrong command, a binary that crashes on startup, a server that rejects its arguments — the next write to its stdin breaks the pipe.
startreported the failure correctly as anMcpHandshakeException, but the broken pipe surfaced separately as aSocketExceptionthat nothing observed, so a caller who caught the documented exception could still lose the isolate to an unhandled error a moment later. The harness now writes through a sink it owns and absorbs the broken pipe there, leaving exactly one catchable failure.Found by running the failure paths inside a guarded zone rather than reading them: the exception at the call site looked right, which is why an ordinary test could not see the problem.
test/dead_server_test.dartnow watches the zone for all three cases (a server that exits at once, a command that does not exist, andcheckServeragainst a dead server).
Still pinned to dart_mcp 0.5.x. Because this package's API hands back
dart_mcp types — the right shape for a conformance prober — a 1.0.0 here has
to wait for that package to stabilise, or freezing would guarantee a major bump
the moment it changes.
0.7.0 #
-
Stop shipping the test runner to consumers.
package:testwas a runtime dependency becauselib/src/matchers.dartimported it — for one function,fail().package:testpulls 25 direct dependencies of its own, includinganalyzer,shelf,coverageandnode_preamble, and every one of them landed in the dependency graph of anything that depended on this package. The import is nowpackage:matcher/expect.dart, which exports the samefail()and brings five small packages, all of whichtestalready depends on. Measured on a scratch project depending on this package: 50 resolved packages before, 16 after.testmoved todev_dependencies, where it belongs.This is breaking only for a consumer that was relying on getting
testtransitively from here; declare it in your owndev_dependenciesinstead.
0.6.0 #
- Seal the exported types.
ConformanceFinding,ConformanceReport,McpServerHarnessandMcpHandshakeExceptioncarried no class modifier, so a later freeze would have made every field added to a report a breaking change for anyone who had subclassed it. None is meant to be subtyped and nothing in the package, its tests or its example does.ConformanceRuleswas alreadyabstract final. No behaviour change.
0.5.1 #
- Fix
utilities/pingignoring the caller's configuredtimeout._checkPingcalledconnection.ping()with no arguments, which falls back to the 1-second default ondart_mcp'sServerConnection.ping, so any server whose ping round-trip took longer than 1 second failed this check even when it answered well inside thetimeoutpassed tocheckServerorMcpServerHarness.start. It now passesharness.timeoutthrough, matching every other request the harness makes.
0.5.0 #
- A composite GitHub Action, so a repository can gate its pull requests on MCP
conformance in a few lines:
uses: Yusufihsangorgel/mcp_probe@v1with acommand, and optionalfail-onandformat. It sets up Dart, activates the CLI, and runs the check, failing the job when a finding at or abovefail-onis present. Inputs are passed through the environment rather than interpolated into the shell, so a value cannot inject script. The package's own CI now exercises the action against a conforming and a non-conforming fixture on every push, so a change that breaks it fails CI. - README notes a real
dart rungotcha:dart runprints a resolution line to stdout the first time, which pollutes a server launched that way, so rundart pub getbefore checking such a server. A compiled, Node or Python server has nothing to resolve.
0.4.0 #
- Machine-readable output and a configurable gate, which is what makes the CLI a
real CI step rather than something a human reads.
ConformanceReport.toJson()(andConformanceFinding.toJson()) render the report as a JSON-serializable map: the probed command, the server identity, asummarycount per severity, and the full findings list. The CLI gains--format jsonto print it and--fail-on error|warning|infoto choose the severity at which the exit code becomes 1 (defaulterror), so a pipeline can fail on a warning and capture a structured report in one run. Invalid flags exit 64 with a usage message.
0.3.3 #
- Install instructions now say
pub addinstead of pinning a version. The pinned number was stale by several releases and would have been stale again after the next one: the README ships frozen in the archive, so a hand-edited version line is wrong the moment anything is published. This one cannot go out of date.
0.3.2 #
example/probe_demo.dartprints a real report without a server of your own. It probes four servers that ship with the package: one that behaves and three that break something specific, so the output shows what a failure looks like before you have written anything to fail. The interesting one is a server that speaks the protocol correctly and is still unusable, because aprinton the way up puts a line on stdout where the transport expects only JSON-RPC. Its own tests would not catch that; what a user sees is a client that will not connect.example/README.mdcovers reading the report, pointing the probe at your own command, themcp_probe checkfront end for a pipeline, and asserting your server's actual behaviour with thetesting.darthelpers.test/readme_snippet_test.dartcompiles the snippet that README prints. It never runs, it only has to analyse, which is enough to keep a copied example from drifting away from the API it is describing.
0.3.1 #
- Declare the diagram in
pubspec.yamlso pub.dev renders it on the package page. It was already in the repository and the README, but pub.dev shows only what thescreenshots:field points at, so the page opened with prose where the picture should have been.
0.3.0 #
- Add the
utilities/pingconformance rule. MCP requires a server to answer apingrequest promptly with an empty result;checkServerand the CLI now send one and report an error if the server times out or answers with a protocol error, so a server that stops responding to liveness pings is caught.
0.2.0 #
- Add a command-line tool.
dart pub global activate mcp_probeinstalls anmcp_probe check <command> [args...]executable that runs a server over stdio, prints each conformance finding, and exits non-zero if any check reports an error, so it drops into a CI step without writing any Dart.
0.1.3 #
listTools,listResourcesandlistPromptsnow follownextCursorpagination and return every page combined. Previously only the first page was fetched, so a conformance run against a paginated server validated just those items and could report the server green without ever seeing the rest.
0.1.2 #
- Docs: tightened the README wording and visuals.
0.1.1 #
- Expand the package description to name what the package does in the words people search for. No code changes.
0.1.0 #
- Initial release.
McpServerHarness: runs an MCP server as a child process over stdio, with per-request timeouts and guaranteed process cleanup.checkServerandConformanceReport: conformance rules for the initialize handshake, declared capabilities, tool definitions, and JSON-RPC error behavior, with Markdown rendering.package:testhelpers in thepackage:mcp_probe/testing.dartentrypoint:expectToolExists,expectToolCallSucceeds,expectToolCallFails,expectResourceExists.