docs: clarify manifest opt-in and optional registration - #377
Conversation
Review of the bilateral terms split found the opt-in caution ambiguous in the same way the App Operator Terms were: it presented registration as the acceptance step while also treating manifest publication as acceptance by conduct, leaving both readings open about what an operator must do before their app can be acted on. dfinity/internetcomputer-org#94 resolves that in the Terms; this states the same model here, since the Terms point at this page for how acceptance happens: - Publishing the Layer 1 manifest opts the app in and constitutes the operator's acceptance of the App Operator Terms. - Publishing enables discovery and read-only interaction; state-changing calls are enabled only after DFINITY confirms the operator's registration, which must be kept current as domains and canisters are added. - Registration includes the app's own privacy-policy URL, so ICP MCP can present it to users. - The privacy sentence now says what the ICP MCP Privacy Policy covers (what is disclosed to a participating app, and what registration processes) and that the operator stays responsible for handling that data lawfully and for keeping the app's own privacy notice accurate, rather than asking operators to "comply with" a notice that describes DFINITY's own processing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
There was a problem hiding this comment.
🟡 Changes recommended
The caution title contradicts the newly clarified Layer 1-specific opt-in trigger.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Clarifies ICP MCP’s two-tier opt-in model and app operator privacy responsibilities.
Changes:
- Defines Layer 1 publication as acceptance.
- Separates read-only access from registered state-changing calls.
- Clarifies privacy-policy responsibilities.
File summaries
| File | Description |
|---|---|
docs/guides/frontends/service-discoverability.md |
Updates the opt-in caution and registration guidance. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Review caught the title contradicting the body it introduces: "Adopting this protocol opts your app in" reads as though any layer opts an app in, while the body pins opt-in to publishing the Layer 1 manifest and says the layers are otherwise independently adoptable. An operator adopting only Layers 2 to 5 got two answers. The title now states the trigger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
Corrects the model stated here. The previous revision gated state-changing calls on DFINITY confirming the operator's registration. That was the wrong branch of the two the review offered: publishing the Layer 1 manifest really is sufficient, so registration is labelled optional instead. Publishing the manifest accepts the App Operator Terms and opts the app into discovery, reads, and state-changing calls for users who authorized actions, with nothing further required. Registration conditions no part of that: it identifies the operator so DFINITY can reach them with notices, records who accepted and which version, and can carry the app's own privacy-policy URL. The operator's own privacy-notice obligation is unchanged. Matches dfinity/internetcomputer-org#96, which makes the same correction in the Terms this page points at. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
The previous revision said a published manifest opts the app into
discovery, reads, and state-changing calls, which overstated what
publication controls. Per review, publication is the condition ICP MCP
applies to state-changing calls specifically: metadata retrieval and
query calls do not require a published manifest at all. That matches the
server, where only the protocol manifest path authorizes a write.
Reviewer's suggestion applied as given, with one pronoun adjusted in the
following sentence so it still reads ("conditions none of it").
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
Second suggestion on the same review, applied verbatim: "Registration is optional and is not a condition of participation", replacing the pronoun phrasing improvised in the previous commit. The rest of the paragraph is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
imcp2 64c48be ("Gate every canister-reaching tool on the discoverability
manifest", dfinity/imcp2#184) restricted every tool that reaches a canister
to canisters a manifest declares: get_canister_candid,
get_canister_api_doc, get_canister_oql_schema, canister_query on both its
paths, and canister_update_call. Reads and writes now share one mechanism
and differ only in what a refusal says.
The caution said the opposite: that publication was the additional
condition for state-changing calls and that ICP MCP did not require a
manifest for metadata retrieval or query calls. Both were accurate when
written. They are not now, so an operator reading this page would expect
their undeclared canisters to stay readable.
It now says publication is the condition for every call that reaches a
canister, and draws the line where the code draws it: an app that publishes
no manifest is still resolved and described, because that surface reaches
no canister, but none of its canisters is read or called. Removal stops new
calls of every kind.
Matches the App Operator Terms sections 3, 4 and 7 as revised in
dfinity/internetcomputer-org#97.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
|
dfinity/imcp2#184 ( So the two suggested sentences ("the additional condition ICP MCP applies to state-changing calls", "It does not require manifest publication for metadata retrieval or query calls") were right when written, on exactly the evidence they cited, and are wrong now. I have overwritten that wording rather than leaving the guide telling operators their undeclared canisters stay readable. Revert me if you would rather handle it separately. What survives from the suggestions is their substance: publication is sufficient, and registration is optional and not a condition of participation. What changed is where the line sits — no longer reads versus writes, but calls that reach a canister versus the surface that does not. @sea-snake your approval was on
Generated by Claude Code |
The caution said an app publishing no manifest "is still resolved and described, but none of its canisters is read or called". Two problems, both raised in review of the companion Terms change. "None of its canisters is read or called" overclaims. Discovery is HTTPS requests to the app's origin, and those are served by the app's own frontend asset canister through the gateway; the x-ic-canister-id header is the gateway naming the canister that answered. The claim is true of the calls ICP MCP makes to a canister, which is what the sentence now says. "Resolved and described" also said nothing a reader could act on. The caution now names the discovery sources a developer would recognise from their own app (the gateway header, /env.json, the JS bundle) and states the consequence #184's own scope note draws: those candidates can no longer be confirmed, so a manifest is the only route from an app to a canister an agent can use. That is the concrete cost of not publishing, which is the thing this caution exists to convey. Matches App Operator Terms sections 4 and 7 as revised in dfinity/internetcomputer-org#97 (60ef171). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
Two sentences still said every layer was independently adoptable, written before this PR made Layer 1 the opt-in act. With publication now the condition for every call ICP MCP makes to a canister, "each layer is independently adoptable" contradicted the caution three paragraphs above it. Both now state the reviewer's wording: Layer 1 is required for participation through ICP MCP, and Layers 2 to 5 remain independently optional and useful once the manifest is published. The claim appeared in two places serving different readers, so it is corrected in both: the closing line of the opt-in caution, and the line introducing the five-layer table. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
Replaces my version of the opt-in paragraph with the reviewer's, which says the same thing in half the words and orders it as a sequence the reader can follow: fetch the public website and manifest to resolve the app, validate the manifest, then retrieve metadata or invoke query or update methods only on canisters it declares. It also states the invalid-manifest case, which mine left out and which the code does handle: per discoverability.rs, "an unreachable origin, an unparseable document, and an absent manifest all refuse". Dropped from mine: the enumeration of discovery sources (the gateway header, /env.json, the JS bundle) and the note that unconfirmable candidates make a manifest the only route to a usable canister. The paragraph reads better without them, and "may fetch the app's public website and manifest to resolve it" carries the part that mattered, which is that the fetching is of public web files and is not a canister call. "No separate registration is required" also goes, since the paragraph below already says registration is optional and not a condition of participation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
|
Cross-checking this page against five wording defects found in review of the companion Terms change (dfinity/internetcomputer-org#97, fixed there in
The fifth: this page ends "Removing the manifest blocks new metadata reads and query or update calls", with no qualifier. In the Terms that is now "once the Service observes the removal", because removal is not instantaneous from ICP MCP's side and an operator relying on it for incident response should know that. I have not changed it here, for two reasons. It is your suggested wording, applied verbatim two commits ago. And the nuance is contractual rather than instructional: a guide telling a developer how to opt out reads worse for the hedge, whereas the Terms need it because an operator may rely on removal as a mitigation. If you want it aligned anyway, the minimal edit is: > Once ICP MCP observes the removal, it blocks new metadata reads and query or update calls. Your call. Everything else on this page matches the Terms as revised. Generated by Claude Code |
Two review decisions. Removal is not instantaneous from ICP MCP's side, so the caution now says "Once ICP MCP observes the removal, it blocks new metadata reads and query or update calls". This matches App Operator Terms sections 4 and 7, which carry the same qualifier, and matters to an operator who removes the manifest expecting an immediate cutoff. The Layer 1 requirement was stated twice in identical words, thirteen lines apart. The caution keeps the full statement, since that is where an operator decides whether to participate. The line introducing the five-layer table now back-references it and leads with what is new at that point in the page, which is that the remaining layers are individually worth adopting. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB
|
Both open questions answered and applied in The observation qualifier, which was the fifth of the five defects found in review of the Terms and the only one that still applied here. The caution's last sentence is now: > Once ICP MCP observes the removal, it blocks new metadata reads and query or update calls. That matches App Operator Terms §4 and §7, which carry the same qualifier, and it matters to an operator who removes the manifest expecting an immediate cutoff. The duplicated Layer 1 sentence is trimmed to a back-reference where it introduced the five-layer table; the caution keeps the full statement. Details on that thread.
The Terms side of this is now merged and live: internetcomputer-org#97 shipped as Version 1.1, effective September 2, 2026, and https://internetcomputer.org/icp-mcp/app-operator-terms/ serves the corrected §3, §4 and §7. So the dependency this page defers to is in place, and this PR is waiting only on a Generated by Claude Code |
Summary
Follow-up to #376. That PR correctly retargeted the opt-in caution from the old single terms of service to the App Operator Terms, but it inherited the ambiguity those Terms carried: it presented registration as the acceptance step while also treating manifest publication as acceptance by conduct, so a reader could not tell what they must do before their app can be acted on.
dfinity/internetcomputer-org#96 resolved that in the Terms themselves. This states the same model here, which matters because the Terms point at this page for how acceptance happens (and say that where the two differ, the Terms prevail).
What the caution now says
/.well-known/ic-architectureopts the app in and constitutes the operator's acceptance of the App Operator Terms. It is sufficient to make the app's declared canisters eligible for everything ICP MCP does with them, queries and state-changing calls alike; no separate registration is required.The five-layer content below the caution is unchanged.
Revision history
This PR went through three models of what publication gates, because the code moved under it:
crates/imcp2-core/src/discoverability.rsgated writes only and itsREADS_ARE_FINErefusal text told agents that reads worked regardless. Both were applied verbatim in60a73a0and8ec933f.e4ce4beundoes that narrowing, because Gate every canister-reaching tool on the discoverability manifest imcp2#184 (64c48be, "Gate every canister-reaching tool on the discoverability manifest") has since made reads gated the same way.get_canister_candid,get_canister_api_doc,get_canister_oql_schema,canister_queryon both paths andcanister_update_callare all restricted to declared canisters; per the module docs, "Reads and writes share one mechanism and differ only in what a refusal SAYS",the_rule()now says the server "reads and calls ONLY canisters an app declares", andREADS_ARE_FINEis gone.So the two suggested sentences were accurate when written and are not now. Step 3 keeps their substance where it still holds (publication is sufficient, registration is optional) and moves the line to where the code now draws it: not reads versus writes, but calls that reach a canister versus the surface that does not.
open_app, the static guides and the identity tools reach no canister and stay ungated, which is why the caution still says an app publishing no manifest is resolved and described.@sea-snake, your approval was on
8ec933f, so this last commit is newer than what you read.Verification
npm run validate— 210 files, all checks passed on each revision, includinge4ce4be(the repo's no-em-dash rule caught new prose in the first draft, fixed before pushing).app-operator-terms/andprivacy-policy/, with no/icp-mcp/terms/link that would send operators to the User Terms.crates/imcp2-core/src/discoverability.rsat imcp2main(64c48be), not from memory.Companion
dfinity/internetcomputer-org#97 makes the matching correction to App Operator Terms §3, §4 and §7. Merge that with or before this, since the Terms are the authority this page defers to.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Xpg83AWtkQo34jbMxpX8WB