@plune-ai/cli 0.34.4 → 0.34.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -124,6 +124,10 @@ the last resort, used only when `PLUNE_TOKEN` is set nowhere else. Nothing write
124
124
  | `plune login` | Save a [Plune platform](https://plune.ai/platform) API token so `sync` and `ingest` can reach it. The token is **checked against the API before it is saved**, so a wrong one fails here rather than two commands later. Get one at `https://beta.plune.ai` → Account → API tokens. Flags: `--token <token>` (omit to paste it or pipe it via stdin), `--skip-verify` (save without checking, for offline setup). In CI, skip this step: every platform command reads `PLUNE_TOKEN` from the environment first, and the saved login only when it is not set. |
125
125
  | `plune logout` | Remove the saved token. |
126
126
  | `plune mcp serve` | Serve the Plune tools to an AI agent (Claude Code, Codex, any MCP client) over **MCP stdio**. See [Plune tools for AI agents](#plune-tools-for-ai-agents-plune-mcp). Flags: `--project <id>` (default `PLUNE_PROJECT`), `--read-only` (offer only the read tools). |
127
+ | `plune mcp check` | Check that **any** MCP server starts and answers: handshake, protocol version, capabilities, the lists, `ping`. See [Is the server alive](#is-the-server-alive-plune-mcp-check). Flags: `--check-timeout <duration>`, `--wait <duration>`, `--smoke` (with `--smoke-limit`, `--smoke-timeout`, `--budget`, `--allow-write-calls`), `--out [<format>=]<path>` (repeatable), `--reporter junit-xml`, `--format human\|json\|github\|markdown`, and the connection flags. Exit `0` healthy, `1` a check failed, `2` the server did not start, could not be reached or wants credentials, or a flag is wrong, `3` something could not be measured. |
128
+ | `plune mcp lint` | Check the tool list of **any** MCP server for what confuses a model — no account, no model. See [Checking any MCP server](#checking-any-mcp-server-plune-mcp-lint). Flags: `--fail-on error\|warn\|info\|never`, `--show-info`, `--format human\|json\|github\|markdown`, `--reporter junit-xml`, `--out [<format>=]<path>`, `--ignore-file <path>`, `--list-rules`, `--call`, `--call-limit <n>`, `--call-timeout <duration>`, and the connection flags (`--url`, `--header-env`, `--env`, …). Exit `0` clean, `1` findings, `2` the server did not start or a flag is wrong, `3` nothing measured. |
129
+ | `plune mcp snapshot` | Write the contract of **any** MCP server — tools, resources, resource templates, prompts, capabilities, instructions — as one stable JSON file to commit. See [Contract snapshots](#contract-snapshots-plune-mcp-snapshot-and-plune-mcp-diff). Flags: `--out <path>` (default stdout) and the connection flags. Exit `0` written, `2` the server did not start or a declared list could not be read (no file is written), `3` the server lists nothing. |
130
+ | `plune mcp diff` | Compare a snapshot with another snapshot file or a live server: every change `breaking`, `non-breaking` or `informational`, with a reason. See [Contract snapshots](#contract-snapshots-plune-mcp-snapshot-and-plune-mcp-diff). Flags: `--fail-on breaking\|any\|none`, `--format human\|json\|github\|markdown`, `--reporter junit-xml`, `--out [<format>=]<path>`, and the connection flags. All three write [JSON, JUnit XML for `plune run import`, GitHub annotations and a pull request comment](docs/guide/cli.md#report-formats-of-plune-mcp-lint-check-and-diff) from one run. Exit `0` nothing at `--fail-on`, `1` a change at it, `2` a file cannot be read or the server did not start, `3` nothing to compare. |
127
131
  | `plune sync` | Upload the latest local run to the platform. Flags: `--file <path>` to send a specific run JSON, `--fail-on-failures` to read the run's summary back once after the upload and exit with [the gate](#a-release-gate---fail-on-failures)'s code. Each upload carries an `Idempotency-Key` (SHA-256 of the body), so sending the same run again returns the same run rather than creating a second one. Against a platform with `POST /v1/jobs` the upload is also reported as a job (kind `sync`, counting the run's rows) that ends completed, or failed with the error text if the sync fails; an older platform without the route is not told, and a job report never fails the sync: when the sync goes through, one the platform did not take is said in one line on stderr. |
128
132
  | `plune run import <file \| folder>` | Turn a **JUnit XML** or **Playwright JSON** report, a **k6 summary** or **Lighthouse JSON** report, a **folder of JUnit XML files** (Maven Surefire's `target/surefire-reports`, Gradle's `build/test-results/test`), or an **Allure `allure-results` folder**, into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json\|allure\|k6\|lighthouse` (detected when omitted: a folder with a `*-result.json` is Allure, any other folder is read as the JUnit `*.xml` files in it), `--name <text>` to call the run something other than the [folder-based default](#what-the-run-is-called), `--min-score <category>=<0-100>` (repeatable) for the score a [Lighthouse](#a-k6-summary-or-a-lighthouse-report) category needs to pass, `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue, `--fail-on-missing-attachments` to exit 1 when a file a JUnit report names with `[[ATTACHMENT\|path]]`, or an Allure result names as a `source`, is not there (the results are sent either way), `--upload-concurrency <n>` for files uploaded at once ([1 to 32, default 16](#many-screenshots-upload-concurrency-and-retries)), `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze when this import finished the run. |
129
133
  | `plune run start` | Open a platform run — or join the one already carrying `--key` — and print its id. Flags: `--key <externalKey>` (generated when absent), `--name <text>` to call the run something other than the [default](#what-the-run-is-called), `--json` for one machine-readable line. |
@@ -228,6 +232,7 @@ code is then the platform's verdict on the run, not the runner's: the summary th
228
232
  | an expected case that never reported (`notRun`): a dead shard is not green | `1` |
229
233
  | only `passed`, `blocked`, `skipped` and muted failures | `0` |
230
234
  | no verdict: the platform could not be reached, the finish was refused, the run was left open or terminated | `1` |
235
+ | no result reached the run and nothing was expected of it: `run import` of a report whose cases the project does not have yet, `run finish` or `sync` of an empty run | `1` |
231
236
  | `run exec` where no result reached the run and nothing was expected of it | the command's own code |
232
237
 
233
238
  Without the flag every command exits as it always did. `plune run` (local evals) is not affected: it stays the
@@ -628,11 +633,15 @@ useful for a self-hosted backend. The Markdown format `pull` writes and `push` r
628
633
  ### Plune tools for AI agents: `plune mcp`
629
634
 
630
635
  `plune mcp serve` gives an agent the same Plune your token reaches — the review queue, cases,
631
- missions, questions, strategy, reports — as MCP tools over stdio. The agent sees at most 20 tools at
632
- once; the rest it finds with `plune_discover_tools`. Every write tool takes `dry_run`, batches stop at
633
- 100 items, and the agent is held to the platform's agent rules: a proposed case lands in the review
636
+ missions, questions, strategy, reports — as MCP tools over stdio. The agent is shown 17 tools, 8 with a
637
+ read token or `--read-only`; five more write tools it finds with `plune_discover_tools`. Every write
638
+ tool takes `dry_run`, batches stop at 100 items, and the agent is held to the platform's agent rules: a proposed case lands in the review
634
639
  queue, a bulk decision needs a confirm, and nothing is deleted through MCP.
635
640
 
641
+ The full guide is [Plune tools for AI agents](https://docs.plune.ai/cli/guides/mcp/): a project
642
+ `.mcp.json` and the Cursor file, the two protocol revisions the server speaks, how to keep the tool list
643
+ small, and what the contract tests check (snapshot, lint, token budget) and what they do not.
644
+
636
645
  `plune_cases_generate` asks the project's AI for case proposals from pasted text (a requirement, a
637
646
  story, a ticket's text; 20 words to 12 000 characters, up to 12 proposals, 8 by default). It spends the
638
647
  project's AI budget, and its proposals wait in the review queue like any other until a person approves
@@ -661,6 +670,110 @@ The server reads the token the way every platform command does: `PLUNE_TOKEN` fr
661
670
  (set it in the client's `env` block), else the login `plune login` saved. A read token, or
662
671
  `--read-only`, offers only the read tools.
663
672
 
673
+ The server speaks both MCP protocol eras: a client that opens with `initialize` (revision
674
+ `2025-11-25` and earlier) and a client on revision `2026-07-28` that sends `server/discover` and
675
+ per-request `_meta`. In the newer revision a client learns that `plune_discover_tools` changed the
676
+ list through `subscriptions/listen`; `tools/list` is sent with `ttlMs: 0`, so a client that does not
677
+ listen reads the current list every time.
678
+
679
+ #### Dependencies
680
+
681
+ | Package | Version | License | Why |
682
+ |---|---|---|---|
683
+ | `@modelcontextprotocol/server` | 2.4.0 | Apache-2.0 | The MCP server and its stdio transport for `plune mcp serve`; it serves revision `2026-07-28` and the `initialize`-based revisions from one process. |
684
+
685
+ The version is pinned exactly, not with a range, on purpose: the 2.x line moves fast, and each update is taken
686
+ deliberately with the protocol tests run against it.
687
+
688
+ ## Test an MCP server
689
+
690
+ Four commands test **any** MCP server, yours or someone else's, started over stdio or reached over
691
+ HTTP. They need no Plune account and no model, and they do not talk to the Plune platform: each one
692
+ starts the server you name after `--`, or connects to the address you give with `--url`, and nothing
693
+ else. Everything after `--` runs as your user, so point them only at a server you would run yourself.
694
+
695
+ ```bash
696
+ npx -y @plune-ai/cli mcp check -- node dist/server.js # does it start and answer
697
+ npx -y @plune-ai/cli mcp lint -- node dist/server.js # what in its tools confuses a model
698
+ npx -y @plune-ai/cli mcp snapshot --out mcp-snapshot.json -- node dist/server.js # its contract, to commit
699
+ npx -y @plune-ai/cli mcp diff mcp-snapshot.json -- node dist/server.js # what changed, and what breaks
700
+ ```
701
+
702
+ | Exit | Meaning |
703
+ |------|---------|
704
+ | `0` | Nothing at the `--fail-on` level, and everything was measured. For `snapshot`: the file was written. |
705
+ | `1` | A finding (`lint`), a failed check or smoke call (`check`), or a change (`diff`) at the `--fail-on` level. `snapshot` has no `1`. |
706
+ | `2` | Nothing about the server is proven, and you can fix why: the command was not found or did not start, the server could not be reached or answered `401` or `403`, a file cannot be read, or a flag is wrong. |
707
+ | `3` | Nothing was measured: the server lists no tools, there is nothing to compare, or a check could not run. Not measured is not a pass. |
708
+
709
+ Each command's own table is in [the CLI reference](docs/guide/cli.md#plune-mcp-check). The guides on
710
+ docs.plune.ai walk through a sample server with three defects, every lint rule with an example, the
711
+ exceptions file, snapshots in a pull request, and the run in Plune through JUnit:
712
+
713
+ - [Test an MCP server](https://docs.plune.ai/cli/guides/mcp-test-a-server/): the four commands, the exit codes and states, stdio and HTTP, `plune run import`;
714
+ - [Lint an MCP server](https://docs.plune.ai/cli/guides/mcp-lint/): the rules, `--fail-on`, `plune-mcp-ignore.yaml`, `--call`;
715
+ - [Snapshot and diff an MCP server](https://docs.plune.ai/cli/guides/mcp-snapshot-diff/): what a change costs a client, and the security signal;
716
+ - [MCP server checks in CI](https://docs.plune.ai/eval-action/recipes/mcp-in-ci/): `plune-ai/eval-action/mcp@v1` for a stdio or an HTTP server.
717
+
718
+ ### Is the server alive: `plune mcp check`
719
+
720
+ `plune mcp check` answers the question before any other: does the server start, finish the
721
+ handshake and answer the basic requests? It runs the checks in order (`start`, `initialize`,
722
+ `protocol-version`, `capabilities`, `tools-list`, `resources-list`, `resource-templates-list`,
723
+ `prompts-list`, `ping`), each with a state and one sentence on what it saw. A list the server did not
724
+ declare is `not-applicable`; a check with no answer within `--check-timeout` is `could-not-run`,
725
+ never a pass.
726
+
727
+ ```bash
728
+ plune mcp check -- node dist/server.js
729
+ plune mcp check --url http://127.0.0.1:3000/mcp --wait 20s
730
+ plune mcp check --smoke --out check.json -- node dist/server.js
731
+ ```
732
+
733
+ `--smoke` also calls the tools that say they are read-only, do not say they are destructive and need
734
+ no argument, with `{}`; `--allow-write-calls` adds only tools that say `destructiveHint: false`. It exits `0` when everything that applies passed, `1` on a failure, `2` when
735
+ the server did not start, could not be reached or wants credentials, and `3` when something could not
736
+ be measured. `--out` writes a report you can attach to a ticket: no URL, command, environment or
737
+ header in it, the server's stderr masked. The states, the options and the exit codes are in
738
+ [the CLI reference](docs/guide/cli.md#plune-mcp-check).
739
+
740
+ ### Checking any MCP server: `plune mcp lint`
741
+
742
+ `plune mcp lint` reads the whole tool list of a server you name, stdio or HTTP, and reports what
743
+ makes a model choose the wrong tool: missing descriptions, look-alike tools, a string where an `enum`
744
+ belongs, a list that costs too much context, schemas that break the specification. Every finding
745
+ has a stable rule id, a level and a line on how to fix it; `--list-rules` prints the catalog.
746
+
747
+ ```bash
748
+ plune mcp lint -- node dist/server.js
749
+ plune mcp lint --url https://example.com/mcp --header-env "Authorization=MCP_AUTH"
750
+ plune mcp lint --call --format json -- node dist/server.js > lint.json
751
+ ```
752
+
753
+ It exits `1` on a finding at `--fail-on` (`error` by default; heuristic advice is `warn` at most),
754
+ `2` when the server does not start, and `3` when nothing was measured — a server with no tools is not
755
+ a clean one. Accepted findings go in `plune-mcp-ignore.yaml`, each with a reason. The options, the
756
+ file's format and the exit codes are in [the CLI reference](docs/guide/cli.md#plune-mcp-lint).
757
+
758
+ ### Contract snapshots: `plune mcp snapshot` and `plune mcp diff`
759
+
760
+ A server's author rarely notices a contract change — a removed tool, a parameter that became
761
+ required, a rewritten description — and clients break later, quietly. `plune mcp snapshot` writes
762
+ the contract as JSON that is the same byte for byte for the same server (sorted keys and entities,
763
+ LF line endings, no time, no command, no URL, no header, secrets masked), so it can live in the
764
+ repository; `plune mcp diff` compares it with a pull request's build and classifies every change.
765
+
766
+ ```bash
767
+ plune mcp snapshot --out mcp-snapshot.json -- node dist/server.js
768
+ plune mcp diff mcp-snapshot.json -- node dist/server.js
769
+ plune mcp diff mcp-snapshot.json current.json --format markdown > comment.md
770
+ ```
771
+
772
+ A changed description, changed instructions, a tool that stops being read-only or becomes
773
+ destructive, and a new tool that does not say it is read-only carry a `security` signal: a reason
774
+ for a reviewer to look, not a failure by itself. The format, the rules and the exit codes are in
775
+ [the CLI reference](docs/guide/cli.md#plune-mcp-snapshot).
776
+
664
777
  ## Programmatic API
665
778
 
666
779
  The same engine that powers `plune run` is exported for use from your own code. Unlike the
@@ -0,0 +1,41 @@
1
+ Third-party notices for @plune-ai/cli
2
+
3
+ This package contains work derived from the projects below. Each entry names the
4
+ project, its author, its licence, its copyright notice and what was reworked.
5
+
6
+ --------------------------------------------------------------------------------
7
+
8
+ mcp-master-tester
9
+ https://github.com/simplymanas/mcp-master-tester (commit 85f0c95)
10
+ Author: Manas Dash
11
+ Licence: MIT
12
+
13
+ What was reworked: the MCP tool lint rules in src/mcp-testing/lint/ take their
14
+ rule groups from public/lint.js of this project (specification checks, confusable
15
+ tools, descriptions, parameters, size of the tool list, naming style), its idea of
16
+ naming the largest tool when the list is too big, its error/warn/info levels and
17
+ its characters-per-token size estimate. The code, the thresholds table, the
18
+ Ukrainian word lists, the rule ids and the tests were written anew; no code was
19
+ copied.
20
+
21
+ MIT License
22
+
23
+ Copyright (c) 2026 Manas Dash
24
+
25
+ Permission is hereby granted, free of charge, to any person obtaining a copy
26
+ of this software and associated documentation files (the "Software"), to deal
27
+ in the Software without restriction, including without limitation the rights
28
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29
+ copies of the Software, and to permit persons to whom the Software is
30
+ furnished to do so, subject to the following conditions:
31
+
32
+ The above copyright notice and this permission notice shall be included in all
33
+ copies or substantial portions of the Software.
34
+
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41
+ SOFTWARE.