MCP Option Conformance
Tracked by pm-v0s2rm, pm-gh1538, and pm-ap7ilf. These repository-only tracking records are excluded from npm.
An integration test can pass while an undeclared option is ignored. That leaves the test asserting a behavior it never exercised. The repository therefore treats emitted MCP unknown-option diagnostics as test failures, while the production server retains its advisory warning behavior for clients.
pm_create and pm_update accept the canonical mutation fields advertised by
their input schemas either at the top level or inside options. pm_run with
the corresponding action uses the same SDK normalization. Explicit nested
options take precedence, including CLI
aliases for the same field. Repeatable inputs, numeric values, and linked-resource
aliases use the shared mutation contracts before persistence. Native SDK run
callers continue to put update fields inside options.
Malformed option containers, values discarded from known scalar fields, and malformed repeatable
entries refuse before execution with invalid_argument_value and
changed: false. Declared boolean mutation fields, their aliases, and receipt
controls must be booleans, including false; this covers clear/replace flags,
parent/dependency exceptions, duplicate allowance, and force. These checks preserve project-defined
custom fields and template-based type resolution while preventing a bad field
from disappearing as a sibling field is written.
Array values that become CLI CSV inputs, such as tags, must contain only
strings and are checked before conversion. Validation follows nested precedence:
an explicit valid nested value replaces a flat value before either is normalized.
The read tools (context, get, list, next, search) and the annotation,
linked-artifact and linked-test tools (comments, notes, learnings,
files, docs, test) hoist every optional parameter their strict action contract declares, derived
from PM_TOOL_ACTION_PARAMETER_CONTRACTS rather than a hand list
(pm-wsqxwb;
tracker record excluded from npm). A flat add therefore writes instead of
falling through to a listing read. The annotation text operand (flat or
nested) is bound to add the way the CLI binds positional text. Equal values
are accepted, and different text and add values are refused with
annotation_text_source_conflict before anything is written. A nested snake_case
spelling of a declared annotation parameter (expect_at, if_absent) is renamed
to the camelCase key the SDK reads, so it cannot silently drop a guard.
For example, { "id": "pm-one", "options": {}, "priority": 4 } changes priority;
with "options": { "priority": 2 }, priority becomes 2. Create also honors its
advertised explicit id, deadline, and other metadata. Regressions check the
discovered schema, persisted values and verified history, and compare item and
history bytes after invalid mutations to prove atomic refusal.
Every run using vitest.config.ts installs McpContractReporter. The reporter records the emitting file, full test name, option, tool, and action, and rejects the run after execution even when all assertions pass. Unattributed warnings also fail. Diagnostics retain option names, never option values.
The sandboxed test runner also retains the reporter when command-line reporter selection overrides the config, including CI coverage shards that emit blobs.
Intentional negative tests must have an exact entry in
MCP_OPTION_WARNING_ALLOWLIST, including a reason. A matching file or test alone
does not exempt other warning identities. The current exemption verifies that
mutation-shaped options cannot mutate a read tool. New integration behavior
should use declared parameters and assert the actual resulting state.
The gate registry registers this check
as mcp-option-contracts. Its
negative control starts a
real Vitest child process whose assertion passes but whose undeclared-option
diagnostic must produce exit status 1. Run the gate and its integration consumers
with the sandboxed repository runner:
node scripts/run-tests.mjs test -- tests/unit/scripts/mcp-contract-reporter.spec.ts tests/integration/mcp-dynamic-package-actions.spec.ts tests/unit/mcp/mcp-server-nested-options.spec.ts
Published MCP acceptance also isolates project and global configuration, tracked by pm-prmt1y. The npm, npx, and bunx checks use temporary tracker roots for both stdio and HTTP servers. This prevents a caller's installed skills from changing discovery pagination and hiding the bundled skills being verified. Protocol and skill-content assertions remain mandatory; acceptance processes disable production telemetry and Sentry.
来自 pm 2026.11.13 中的 docs/MCP_OPTION_CONFORMANCE.md。 在 GitHub 上查看