diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index f3845a37..56b98924 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -810,7 +810,7 @@ For each language recon cleared, do the AST work and produce a `RepoInventory`: `#[...]` is parsed as a `comment` node — so the attribute is read from the comment text immediately preceding the method via regex. Emits `ToolDef{Kind: mcp_tool, Language: php}`, so deriveSDKsDetected stamps SDKMCP - and the mcp/ pack's `language: php` rules (MCP-019/020) audit them. Multi-line + and the mcp/ pack's `language: php` rules (MCP-019/020/029) audit them. Multi-line `#[...]` attributes, `#[McpResource]` / `#[McpPrompt]`, and PHP body-fact predicates are v1 gaps. - **DiscoverRustMCPTools** (`rust_mcp.go`) — Rust MCP tools parsed with diff --git a/internal/rules/policies_test.go b/internal/rules/policies_test.go index 65af6c0a..f2a58523 100644 --- a/internal/rules/policies_test.go +++ b/internal/rules/policies_test.go @@ -1361,6 +1361,21 @@ def run_cmd(name: str) -> str: kind: models.KindMCPTool, lang: models.LanguagePHP, wantFires: false, src: " Rename the method (or set the `#[tool]` `name = "..."` argument) to a verb-object form, e.g. `summarize_invoice`, `fetch_weather`. + + - id: MCP-029 + title: PHP MCP tool has no type-annotated parameters + severity: medium + confidence: 0.85 + language: php + applies_to: + - mcp_tool + scope: tool + match: + has_params: true + has_typed_params: false + explanation: > + MCP derives a PHP tool's advertised input JSON schema from the handler's + parameter type hints. PHP type hints are optional; without them the + published schema is unconstrained, so connecting models send unvalidated + inputs that frequently cause runtime errors inside the server. Go, C#, + and Rust MCP tools cannot express this gap — those languages are + statically typed — which is why this sibling of MCP-002 exists only for + PHP. + fix: > + Add type hints to every parameter (`function search(string $query, int + $limit = 10): array`). Use typed properties or DTO classes for structured + inputs so the published schema constrains them.