Pular para conteúdo

AUR-021: Fixar MCP conformance e segurança

Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.

This is a research/decision card. It does not ship an executable feature or start any MCP server; it fixes a design contract a later O11-mcp card implements against. The observable behavior is the acceptance lint itself: tests/acceptance/AUR-021.sh deterministically resolves the artifacts below and either passes or names exactly which one is incomplete.

Behavior

tests/acceptance/AUR-021.sh (selector AC-001) reads six artifacts this card owns and checks that they resolve to one consistent, testable pin, without making any network request:

  1. .board/research/mcp.md — contains, case-insensitive, every term listed in tests/specs/AUR-021/required-terms.txt (stdio, read-only, OAuth, injection, capability at time of writing), and a ## Sources matrix table with at least 5 data rows, each citing a [label](url) source whose host is allowlisted (tests/specs/AUR-021/allowed-source-domains.txt), a parseable version, an ISO-8601 date, and a non-empty "what it fixes" cell.
  2. standards/mcp/protocol.yaml — declares protocol.version as an ISO-8601 date and go_sdk.module / go_sdk.version as a semantic version; both version strings must also appear verbatim in .board/research/mcp.md, so the pinned standard cannot silently diverge from the source that justifies it.
  3. standards/mcp/tools.yaml — every declared tool has class: read_only or class: mutable; every mutable tool sets requires_explicit_consent: true and no read_only tool sets it; every tool named in tests/specs/AUR-021/required-mutable-tools.txt (review.publish at time of writing) is present, classified mutable, and requires explicit consent.

Contract

  • tests/specs/AUR-021/required-terms.txt, tests/specs/AUR-021/allowed-source-domains.txt, and tests/specs/AUR-021/required-mutable-tools.txt are the single source of truth for, respectively, the literal terms the research document must contain, the hostnames a Sources matrix link may cite, and the tools that must be classified mutable with explicit consent. The shell acceptance test reads all three instead of duplicating the lists.
  • A Sources matrix row's Version cell must match a semantic-version-like pattern (v1.6.1) or an ISO-8601 date, optionally followed by free text (2026-07-28 (RC locked 2026-05-21)); its Date cell must be a plain ISO-8601 date.
  • standards/mcp/tools.yaml's tool classification does not trust any MCP server's own self-reported readOnlyHint/destructiveHint annotations (the MCP specification itself treats those as untrusted unless the server is already trusted); it is this project's own, independently fixed policy.
  • This card produces no executable MCP server, transport, or tool registry. The protocol/SDK pin and tool classification it fixes here are consumed by a dependent O11-mcp card, not built here.

Limits

standards/mcp/protocol.yaml fixes the two pins this baseline requires:

  • protocol.version: the adopted MCP specification revision (2025-11-25); protocol.transports: the transports this baseline recognizes (stdio, streamable-http).
  • go_sdk.module / go_sdk.version: the adopted Go SDK (github.com/modelcontextprotocol/go-sdk v1.6.1).

standards/mcp/tools.yaml fixes, per tool, a class of read_only or mutable, and for every mutable tool a requires_explicit_consent: true flag that a future server implementation must enforce before invocation.

Example (no secret)

Running the acceptance test directly, with no network access and no secret material of any kind:

$ ./.board/bin/oci-run --profile bootstrap-readonly-v1 --card AUR-021
{"card":"AUR-021","scenario":"AC-001","selector":"AC-001","required_terms":5,"source_rows":7,"result":"pass"}

A failing example — review.publish reclassified read_only in standards/mcp/tools.yaml:

$ tests/acceptance/AUR-021.sh
AUR-021/AC-001/tool-misclassified: required tool review.publish must be class: mutable with requires_explicit_consent: true, got class=read_only requires_explicit_consent=

Diagnosis

  • AUR-021/AC-001/behavior-missing: required artifact absent: <path> — one of .board/research/mcp.md, standards/mcp/protocol.yaml, standards/mcp/tools.yaml, or a tests/specs/AUR-021/* fixture is missing or empty. Restore it from the card's owned paths.
  • AUR-021/AC-001/behavior-missing: required term missing from .board/research/mcp.md: <term> — one of the five required terms was removed or renamed; restore it, case-insensitively.
  • AUR-021/AC-001/source-not-versioned: ... — a Sources matrix row is missing, cites a non-allowlisted host, has no versioned Version cell, has a non-ISO Date cell, or a pin's version string in standards/mcp/protocol.yaml no longer appears in the research document. Fix the offending cell or restore the citation.
  • AUR-021/AC-001/tool-misclassified: ... — a tool in standards/mcp/tools.yaml has an invalid class, a mutable tool is missing requires_explicit_consent: true, a read_only tool wrongly sets it, or a required mutable tool (review.publish) is missing or reclassified. Fix the tool's class/requires_explicit_consent fields.
  • AUR-021/AC-001/infrastructure: ... — a required host tool is missing or the repository root could not be resolved; this is never a behavioral result and never counts as RED evidence for this card.

History: Integration proof path was escalated and resolved at v2

At version: 1, this card's declared paths entry and TDD-proof "Integration" line named tests/integration/AUR-021.go::IntegrationAUR021. A .go file without the _test.go suffix is invisible to go test's scanner by definition of the Go toolchain, and IntegrationAUR021 was not Test-prefixed either, so that path could never carry a real, discoverable Integration proof — the same defect AUR-020's card carried at version: 1 (tests/integration/AUR-020.go::IntegrationAUR020), which round 1 vetoed as dead code and round 2 vetoed as a working test delivered outside the card's declared paths, resolved only by a governance version bump (.board/cards/ready/AUR-020.md v2) retargeting the path to tests/integration/AUR-020_test.go::TestAUR020Boundary.

Because .board/cards is this card's own forbidden_paths entry, the builder could not make that same correction from inside the card. Per the board's rule that an unimplementable spec is escalated rather than silently worked around, no file was written at either the declared dead-code path or an undeclared _test.go path in that round.

Governance resolved the escalation the same way it resolved AUR-020's: a version bump to version: 2 (.board/cards/doing/AUR-021.md) retargeted the TDD-proof "Integration" line to tests/integration/AUR-021_test.go::TestAUR021Boundary. That file is now part of this card's delivered paths, is discovered by go test ./... with no external dispatcher, and is the Integration evidence this document and the acceptance test currently rely on.