Core result: HTTP methods carry useful semantics, but those semantics set a limit. Under the profile's effect-faithful translation assumption, GET supports a read-only inference, PUT and DELETE support idempotence, and POST and PATCH support no positive Core guarantee from the method alone. The checker evaluates all 40 combinations of the five methods and three covered MCP annotations.
The question
An API-to-tool translator usually needs to describe what a generated tool may do. MCP ToolAnnotations include hints such as readOnlyHint, destructiveHint, and idempotentHint. Downstream systems may use those hints when they plan, approve, or repeat an action.
The translator often knows the HTTP method. That method says something real about the operation, but it does not say everything. The risk is straightforward: a translator can attach a guarantee that the source method never supplied.
GET has standardized safety semantics, so a faithful translation has a basis for a read-only claim. PUT and DELETE are standardized as idempotent. POST, however, does not generally mean additive-only, and PATCH is not generally non-destructive or idempotent. Those stronger properties need some basis beyond the method name.
What each method can support
The Core covers five methods and asks only what follows from their standardized semantics under RFC 9110 and RFC 5789.
For GET, the profile treats read-only as also satisfying additive-only and idempotent at the requested-effect level: if the requested operation makes no modification, it also makes no destructive modification and repeating it adds no requested modification. In MCP, the cleanest GET representation is readOnlyHint=true. Once read-only is active, the two dependent raw hints are not used for the Core decision.
The soundness check
The checker first resolves the annotation state into the guarantees it actively asserts. readOnlyHint=true activates READ_ONLY. For a non-read-only tool, destructiveHint=false activates ADDITIVE_ONLY, and idempotentHint=true activates IDEMPOTENT.
It then compares those active claims with the guarantees justified by the HTTP method.
A translator can remain conservative and still be sound. It may leave a justified guarantee unstated. The failure case is narrower: an active annotation claims something the method does not support.
The 40-state oracle
Each of the three covered annotation fields is boolean, so there are eight raw annotation states for each method. Across five methods, that gives 40 states. The oracle evaluates all of them rather than sampling a few familiar mappings.
- Methods
- GET, POST, PUT, PATCH, DELETE
- Annotation states per method
- 8
- Total oracle states
- 40
- Sound states
- 14
- Unsound states
- 26
- Profile-maximal states
- 8
- Runtime dependencies
- 0
Some raw states become semantically equivalent because readOnlyHint=true makes the dependent fields inactive, but the full 40-state surface is still checked. Version 0.2.1 preserved every substantive v0.2.0 classification and complete checker result.
Concrete cases
- GET with readOnlyHint=true: supported, assuming the generated tool preserves the GET operation's requested effect. This is the profile-maximal GET representation.
- POST with destructiveHint=false: for a non-read-only tool, that asserts an additive-only guarantee. POST semantics do not support that guarantee in general, so method-only inference is unsound.
- PUT with idempotentHint=true: supported by PUT's standardized idempotence. PUT can still replace existing state, so the method alone does not support an additive-only claim.
- PATCH with idempotentHint=true: unsupported as a general method rule. A particular PATCH operation may be idempotent, but that requires operation-specific evidence.
- DELETE with idempotentHint=true: supported. Idempotence does not make deletion non-destructive.
The assumption behind the result
The profile applies only when the HTTP method still faithfully describes the generated tool's requested or intended effect for the guarantee being carried over. It calls this effect-faithful translation.
A tool that performs GET /account and also requests a write to another store cannot inherit a read-only claim merely because one part of the tool uses GET. For idempotence, repeated MCP calls with the same arguments must preserve equivalent operation-relevant HTTP request semantics. The requests do not have to be byte-identical: request IDs, authentication tokens, or tracing metadata may change while the requested operation remains equivalent.
The checker assumes this condition. It does not inspect wrapper runtime behavior to establish it.
Soundness and precision
Soundness asks whether the translator overclaims. PROFILE_MAXIMAL asks a different question: among the sound states, does this one express the strongest Core representation the method can justify?
Maximality is only a precision measure. MCP does not require it, and SOUND_NON_MAXIMAL is not a failure. The profile is concerned first with unsupported guarantees, not with forcing every translator to claim as much as possible.
Comparison with reproduced defaults
The artifact also reproduced method-default mappings from three independent implementation sources and evaluated those specific mappings under the same Core.
API7's documented defaults matched the profile-maximal mapping for all five methods. In the frozen Infobip mapping, the reproduced POST, PUT, and PATCH defaults asserted additive-only guarantees that the method alone did not justify. In the frozen Azure mapping, POST and PUT asserted additive-only guarantees, while PATCH asserted both additive-only and idempotent guarantees.
These are scoped results for the pinned method-default mappings that were reproduced. They are not ratings of API7, Infobip, or Azure as products.
A second check against real operations
The project kept a separate semantics-blind witness set so the method-level rule could also be checked against concrete, first-party-documented operations. The frozen set contains 25 method-stratified operations and eight unique operation-level evidence records. It is a witness set, not a prevalence sample.
Six matched contradiction witnesses showed POST, PUT, and PATCH operations that edit, replace, or delete existing state. Those cases give concrete counterexamples to a universal method-only rule that these methods are non-destructive.
The same annex also contains one operation-specific additive-only POST supported by a DaniWeb record. A Jumpseller support record was version-mismatched and remained non-decisive. Across the eight unique evidence records, one changed the decision, six changed the reasoning only, and one was non-decisive. The evidence favored keeping the Core static and treating operation-specific proof exceptions as a separate experiment.
Result
Within this five-method profile, a translator that derives MCP tool hints from the HTTP method should not assert an active guarantee beyond what that method actually supports. The executable checker turns that boundary into a deterministic test.
The result is limited to the declared five-method HTTP-to-MCP profile. It is not a general translation theory.
Where the profile stops
The checker answers one bounded question: assuming effect-faithful translation, do the method-derived annotations claim more than the method supports? Runtime behavior, tool safety, server honesty, HTTP compliance, and MCP server trustworthiness are outside that check. The profile also does not validate explicit operation-specific annotations, cover every HTTP method, or turn the frozen implementation comparisons into product-level judgments. The 25-operation annex is not an ecosystem prevalence estimate. Version 0.2.1 remains an experimental draft for public review, not an official MCP, IETF, OpenAPI, vendor, or standards-body profile.
Frozen record and reproducibility
Version 0.2.1 clarified the applicability condition, status, framing, packaging, and machine-readable metadata. It did not change the v0.2.0 decision model, any of the 40 classifications, the substantive translator findings, or the empirical corpus.
- The separate 54-file v0.2.0 object remains byte-for-byte unchanged and passes 32 of 32 baseline tests.
- V0.2.1 strict typecheck, build, deterministic generation, and all 36 tests pass in the frozen record.
- The vectors and translator artifacts were regenerated twice without byte changes.
- The empirical machine artifact and frozen sampler hashes verify exactly.
- A clean extraction with no sibling project or upstream checkout can install from the lockfile and pass pnpm verify.
- Runtime dependency count is zero. TypeScript 5.9.3 is the sole pinned development dependency.