Skip to content

Refuse update calls to known finance-related canisters - #163

Open
aterga wants to merge 15 commits into
mainfrom
claude/icp-marketplace-compliance-vpawel-7-finance-canister-disallow
Open

Refuse update calls to known finance-related canisters#163
aterga wants to merge 15 commits into
mainfrom
claude/icp-marketplace-compliance-vpawel-7-finance-canister-disallow

Conversation

@aterga

@aterga aterga commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Extends the financial-transactions guard in two ways. First, manage_neuron — the one standardized method through which NNS and SNS governance neurons are disbursed, split, and spawned — joins the always-refused method names alongside the ICRC transfer/approval surface, covering every SNS DAO's governance (54 exist today, more launch by NNS proposal) and every future one with no list to go stale. Second, a curated, labeled disallow list of finance-related canisters on which canister_update_call refuses every update method — closing the gap where value could still move through non-standardized methods (a DEX swap, a minter withdrawal) that no method-name list can enumerate. Each canister entry carries two labels — what service it provides, and how it is finance-related — interpolated verbatim into the refusal, e.g.:

swap is an update call to the Sonic exchange swap canister — its deposit, swap, and liquidity calls move tokens between user subaccounts and pools. State-changing calls to financial services are not supported by this server, to protect the user: asset-moving requests are denied. …

The canister list (52 entries — count verified programmatically, per review)

Every id was verified against the IC dashboard's canister registry (ic-api.internetcomputer.org, exact registered names) and the services' own published sources (their canister_ids.json / manifests / docs / on-chain SNS records) on 2026-08-28; the dashboard-unnamed entries are each pinned by a project-official source (DFINITY's own repos, apps' own /.well-known/ic-app.json manifests, live x-ic-canister-id headers, SNS proposal payloads).

  • The network's own funds infrastructure (6): NNS Governance (its whole update surface, beyond manage_neuron), both NNS dapp frontends (classic qoctq… and current mc7vh… origins), the Genesis Token canister (claim_neurons), the ICP ledger, the cycles ledger.
  • Chain-key minters (3) — they move real assets on other chains: ckBTC (retrieve_btc), ckETH/ckERC20 (withdraw_eth/withdraw_erc20), ckDOGE (retrieve_doge).
  • All 14 mainnet chain-key token ledgers (ckBTC, ckETH, ckUSDC, ckUSDT, ckEURC, ckWBTC, ckWSTETH, ckLINK, ckUNI, ckSHIB, ckPEPE, ckXAUT, ckOCT, ckDOGE).
  • Wallets (5): the Oisy backend, the Chain Fusion Signer (signs and broadcasts Bitcoin transactions; its eth/ecdsa/schnorr signatures move funds on other chains), Oisy Trade, the Oisy rewards canister, the wallet frontend.
  • Liquid staking (3): the WaterNeuron protocol canister (ICP deposits, nICP minting, unstaking withdrawals), the nICP ledger, and its frontend — pinned by WaterNeuron's own canister_ids.json.
  • Exchanges (21): MULTI/DEX (backend, bridge, frontend — self-declared by the app's own /.well-known/ic-app.json); ICPSwap (SwapFactory, PasscodeManager, farm + staking-pool factories, frontend); Sonic (swap canister, LBP registry, vesting, plus the XTC and WICP DIP-20 ledgers — their legacy transfer/mint names are exactly what the standardized-methods group deliberately does not match, so the canister entries close that documented gap for the two most prominent legacy ledgers); ICDex/ICLighthouse (router, DexAggregator, DAO trader, trading-mining, frontend); ICPEx (router, token-creation service, frontend).

Deliberately not listed

  • Per-SNS governance canisters — covered by the manage_neuron method rule instead (per review): a static list of 54 DAOs (a third of them aborted swaps, some renamed or folded) would go stale the day the next SNS launches, while the method rule covers them all, present and future.
  • KongSwap — removed per review: the service no longer exists.
  • CMC — its notify_create_canister/notify_top_up are the documented recovery path for a user's own interrupted icp-CLI funding flow.
  • Read-only canisters (ledger indexes/archives, the exchange-rate canister, oracles/validators/loggers) — no value-moving update surface.
  • Dynamically created canisters (ICPSwap per-pair pools/farms, ICDex per-pair orderbooks, per-SNS ledgers): a static list cannot enumerate them; the module docs say so, and the standardized-methods group plus the stated policy cover them.
  • Undeployed (the reserved ckSOL ids — no code installed yet) and role-undocumented project canisters (e.g. two SNS-registered WaterNeuron dapp canisters whose roles have no published id mapping).

Mechanics

  • Method-level refusals keep precedence, so their tailored messages survive: a cycles-ledger creation spend still points at the user-run icp CLI, an ICRC hit still names the standard method; the canister blanket catches everything else on listed canisters (pinned by a test).
  • Tests: manage_neuron refused on any canister; every canister entry refuses arbitrary update names with both labels + the protective policy wording and no marketplace/compliance jargon; the list is well-formed (valid, unique principals; non-empty labels); precedence pinned. The literal-matching test demonstrates on an unlisted canister (on a listed one, everything is refused regardless of spelling).
  • Description surfaces updated in step: SERVER_INSTRUCTIONS, the README tool-table row, both directory docs' guard bullets, and the landing page's two "refused by design" strings — all four now name the manage_neuron rule alongside the ICRC names (per review). Per review, the directory docs state the posture present-tense only — no history of past functionality.

Also in this PR

The NNS is dropped from the known-app registry (separate commit): the name registry exists to route agents to well-known apps, and routing them to a staking/funds frontend sits badly with the not-a-financial-tool posture — so open_app("nns") no longer resolves, no repair guidance points at it, and the unknown-app note no longer enumerates it. The KNOWN_DERIVATION_ORIGINS mappings stay: a user who brings an NNS URL themselves still derives the correct per-app identity for reads (instead of a silently wrong, empty-looking one), and update calls to the NNS canisters are refused by the new guard.

Verification

  • cargo test workspace-green: 153 core + 20 local tests.
  • cargo clippy at the existing 10-warning baseline.
  • All researched ids batch-verified against ic-api.internetcomputer.org before curation (exact name matches, or unnamed-but-source-pinned; rejected/undeployed ids excluded).

🤖 Generated with Claude Code

https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

claude added 2 commits August 28, 2026 09:26
The name registry exists to route agents to well-known apps; routing
them to a staking/funds frontend sits badly with the server's
not-a-financial-tool posture, so the NNS entry is removed: no name
resolution for "nns", no repair guidance toward it, and the unknown-app
note no longer enumerates it. The KNOWN_DERIVATION_ORIGINS mappings
stay: a user who brings an NNS URL themselves still derives the correct
per-app identity for reads instead of a silently wrong (empty-looking)
one, and update calls to the NNS canisters are refused by the
finance-canister guard added alongside this change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Adds a third group to the financial-transactions guard: a curated,
labeled disallow list of canisters whose purpose is holding, staking,
exchanging, or moving value. On these, canister_update_call refuses
EVERY update method; each entry carries what the service is and how it
is financial, and the refusal interpolates both labels verbatim.

The list (49 entries, every id verified against the IC dashboard's
canister registry and the services' own published sources on
2026-08-28):

- The network's own funds infrastructure: NNS Governance
  (manage_neuron disburses neuron-held ICP), both NNS dapp frontends,
  the Genesis Token canister, the ICP ledger, the cycles ledger.
- Chain-key minters (they move REAL assets on other chains): ckBTC,
  ckETH/ckERC20, ckDOGE.
- All 14 mainnet chain-key token ledgers.
- Five prominent SNS governance canisters (OpenChat, Gold DAO,
  WaterNeuron, KongSwap, Dragginz) — the same disburse pattern.
- Wallets: the Oisy backend, the Chain Fusion Signer (signs and
  broadcasts Bitcoin/Ethereum transactions), Oisy Trade, the Oisy
  rewards canister, and the wallet frontend.
- Exchanges: ICPSwap (SwapFactory, PasscodeManager, farm and
  staking-pool factories, frontend), KongSwap (backend, treasury
  extension, frontend), Sonic (swap, LBP registry, vesting, plus the
  XTC and WICP DIP-20 ledgers whose legacy transfer names the ICRC
  group deliberately does not match), ICDex/ICLighthouse (router,
  DexAggregator, DAO trader, trading-mining, frontend), and ICPEx
  (router, token-creation service, frontend).

Method-level refusals keep precedence, so the tailored messages
survive (a creation spend still points at the icp CLI; an ICRC hit
still names the standard method); the canister blanket catches
everything else on listed canisters. The CMC stays deliberately
unlisted (its notify_* calls are the documented recovery path), as do
read-only indexes/archives and the exchange-rate canister. The module
docs note the honest limit: exchanges create per-pair pool canisters
dynamically, so the list covers each service's central canisters and
the ICRC method group plus the stated policy cover the rest.

Tests: every entry refuses arbitrary update names with both labels and
the protective policy wording; the list is well-formed (valid, unique
principals, non-empty labels); method-level precedence is pinned. The
server instructions, README tool table, both directory docs, and the
landing page now state the canister-level refusal alongside the method
refusals.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Comment thread crates/imcp2-core/src/compliance.rs Outdated
Per maintainer review on #163: the service no longer exists (its site
and repository are gone), so its backend, treasury extension, frontend,
and SNS governance come off the list — a dead service does not meet the
list's prominence bar. The list stands at 45 entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Comment thread docs/anthropic-directory-submission.md Outdated
Comment thread docs/openai-directory-submission.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a finance-canister denylist so all update calls to curated financial services are refused, while retaining method-specific precedence.

Changes:

  • Adds and tests 45 labeled finance-canister restrictions.
  • Removes NNS from name-based app discovery while preserving explicit URL identity derivation.
  • Updates policy documentation and landing-page messaging.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/imcp2-core/src/compliance.rs Implements and tests the denylist.
crates/imcp2-core/src/tools.rs Updates server policy instructions.
crates/imcp2-core/src/discover.rs Removes NNS name resolution.
README.md Documents update-call restrictions.
docs/openai-directory-submission.md Updates OpenAI policy explanation.
docs/anthropic-directory-submission.md Updates Anthropic policy explanation.
src/assets/index.html Updates landing-page policy text.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/imcp2-core/src/compliance.rs Outdated
Comment thread crates/imcp2-core/src/compliance.rs
Comment thread crates/imcp2-core/src/compliance.rs Outdated
Per maintainer review on #163: the submission docs read as if a gap had
been closed at some point, rather than describing a product that simply
does not support financial transactions. The financial sections of both
directory docs now state the posture present-tense only — the
"(resolved in code)" heading, the shipped-mitigations lead with its PR
citations, the "execution paths that once moved funds are removed from
the binary" sentences, the "per maintainer review" attributions, and
the "Status: resolved in code" gap-closure paragraph are gone. The
mcp-review email logistics stay (no reply needed; answer with the
stated posture if one arrives), and the production-gap blocker keeps
its operational fact (deploy a release from current main before
submitting) without dwelling on what the old build serves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Comment thread crates/imcp2-core/src/compliance.rs Outdated
Comment thread crates/imcp2-core/src/compliance.rs
Answering review on #163 ("why not list all SNS governance
canisters?"): enumerating them can't stay current — 54 SNS DAOs exist
today (a third of them aborted swaps, some renamed or folded) and new
ones launch by NNS proposal. Their value-moving surface is one
standardized method, so the guard now refuses `manage_neuron` on EVERY
canister, the way it refuses the ICRC transfer/approval names: that
covers each existing SNS DAO's governance, every future one, and the
NNS's, with no list to go stale. The four per-DAO governance entries
come off the canister list (the NNS Governance entry stays — the
network's own governance keeps its whole update surface refused), and
the standardized-methods group is renamed and re-documented to say it
carries both the ICRC token surface and the governance interface.

Also per review: the Chain Fusion Signer label had an accidental run of
spaces (interpolated verbatim into refusals) — collapsed; and the gate
function's doc now describes all three refusal scopes instead of the
stale "both groups" wording.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
@aterga
aterga marked this pull request as ready for review August 28, 2026 10:01
@aterga
aterga requested review from a team and Copilot August 28, 2026 10:01
Per review on #163. WaterNeuron (liquid staking): the water_neuron
protocol canister (ICP deposits, nICP minting, unstaking withdrawals),
the nICP ledger, and the frontend — ids pinned by the project's own
canister_ids.json and the dashboard registry; the nICP index/archive
(read-only) and the icrc_validator (proposal validator) stay off, as do
the two SNS-registered dapp canisters with no documented role. MULTI/DEX
(exchange): its backend, bridge, and frontend, self-declared by the
app's own /.well-known/ic-app.json manifest (the frontend id also
matches the live x-ic-canister-id header and the known-app registry).
The list stands at 47 entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/imcp2-core/src/compliance.rs:138

  • The PR description calls this a 41-entry canister list, but the static contains 46 entries (44 inline IDs plus ICP_LEDGER and CYCLES_LEDGER). Update the stated count, or remove any unintended entries, so the documented review scope matches the implemented guard.
const DISALLOWED_FINANCE_CANISTERS: &[(&str, &str, &str)] = &[

Comment thread README.md Outdated
Comment thread docs/anthropic-directory-submission.md Outdated
Comment thread docs/openai-directory-submission.md Outdated
Comment thread crates/imcp2-core/src/tools.rs
Comment thread src/assets/index.html Outdated
Copilot AI review requested due to automatic review settings August 28, 2026 10:05
Review on #163: the guard refuses manage_neuron everywhere, but the
server instructions, README tool row, both directory docs, and the
landing page still enumerated only the ICRC methods, the ledger-scoped
methods, and the canister list — understating the guard and leaving SNS
neuron coverage unexplained. All four surfaces now name the governance
method alongside the ICRC names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

crates/imcp2-core/src/compliance.rs:138

  • The PR description identifies this as a 47-entry list, but the constant contains 52 entries (6 infrastructure + 3 minters + 14 ledgers + 5 wallets + 3 WaterNeuron + 3 MULTI/DEX + 5 ICPSwap + 5 Sonic + 5 ICDex/ICLighthouse + 3 ICPEx). Reconcile the five-entry discrepancy or update the PR description so the audited inventory count is accurate.
const DISALLOWED_FINANCE_CANISTERS: &[(&str, &str, &str)] = &[

docs/openai-directory-submission.md:120

  • The directory submission's exhaustive guard description omits the new global manage_neuron rule. Because per-SNS governance canisters are intentionally not in the curated list, the current wording understates the protection added by this PR. Include manage_neuron among the standardized methods refused on every canister.
  `manage_neuron` — neuron staking and disbursement — on every canister,
  plus the ICP and cycles ledgers' own
  value-moving methods on those ledgers, plus every update call on a curated

crates/imcp2-core/src/tools.rs:2009

  • The documented refusal scopes omit the new global manage_neuron rule. Per-SNS governance canisters are deliberately absent from the curated list, so these server instructions currently do not disclose the restriction that provides coverage for every SNS. Include the NNS/SNS manage_neuron method alongside the globally refused ICRC methods.
             equivalents) AND the governance method manage_neuron (neuron staking/disbursement, \
             on the NNS and every SNS) on every canister, the ICP and cycles ledgers' own \
             transfer/withdrawal/creation methods on those ledgers, and EVERY update call on a \
             curated list of known financial-service canisters (token ledgers and minters, \

Comment thread README.md Outdated
Comment thread docs/anthropic-directory-submission.md Outdated
Copilot AI review requested due to automatic review settings August 28, 2026 10:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment thread crates/imcp2-core/src/compliance.rs
Comment thread docs/anthropic-directory-submission.md
Comment thread docs/openai-directory-submission.md Outdated
…names

Three review points on the finance-canister disallow list, plus one
risk-reduction change:

- The cycles-minting canister's update surface is refused. Its four
  user-callable methods (notify_top_up, notify_create_canister,
  notify_mint_cycles, create_canister) each complete a funding
  operation: the ICP debit happened earlier, but the call is what
  finishes the flow, which makes it a concrete financial path rather
  than a theoretical one. Their refusal points at the icp CLI, which is
  also how an interrupted mint is recovered — so the recovery path is
  preserved, just not through the connector. The review named the two
  notify_* completions; the other two are the same interface and the
  same class of call, so all four are listed together.

- canister_update_call's description discloses the refusal. Both
  directories require a description to match actual behavior, and
  OpenAI's guidelines say a side effect must never be implicit, so the
  description now carries one factual sentence: financial operations and
  update calls to known financial-service canisters are not supported
  and return an error. The full policy — refused method families and the
  reason — stays in the server-level instructions rather than being
  restated per tool. The test that prohibited the word "financial" in
  that description is replaced by one that pins the disclosure.

- No refusal names a venue any more. Refusal messages, the server
  instructions, the README, the landing page, and the submission doc all
  now say the operation belongs outside the connector, in a trusted
  interface the user controls, instead of naming a wallet. Metadata that
  answered a refused financial operation with a specific transactional
  service would read as a redirect from one such route to another.
  Canister creation and funding keep the icp CLI pointer: that is the
  user's own tooling, and this connector already says that work happens
  there.

- The OpenAI submission's policy section is corrected. It claimed that
  OpenAI's restriction was usefully narrower than Anthropic's; it is
  not — the app guidelines prohibit execution of money transfers, crypto
  transfers, and investment trades outright. The section is rewritten
  around the same non-financial posture the Anthropic submission states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 10:45

aterga commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

All three requested changes are in 48002b5, plus the risk-reduction one. Summary of what landed, and the two places I went slightly beyond the letter of the request:

1. OpenAI policy analysis — corrected. You're right, and the old section was wrong in a way that mattered: it read the restriction as narrower. Section 3 of docs/openai-directory-submission.md is rewritten around the same non-financial posture as the Anthropic submission, quoting the app guidelines directly — "execution of money transfers, crypto transfers, or investment trades" is prohibited outright, alongside the speculation/consumer-deception clause. The commerce rules are handled separately as what they are (nothing to attach to: the plugin sells nothing), rather than as the reason the attestation is satisfiable.

2. CMC — blocked, and I extended it to four methods. You named notify_create_canister and notify_top_up. Fetching the CMC's interface, its complete user-callable update surface is four methods: those two plus notify_mint_cycles (mints cycles to a cycles-ledger account) and create_canister (creates a canister from attached cycles). All four are the same class of call by your own criterion — each one completes a funding operation — so listing only two would have left the same concrete path open under a different name. The remaining CMC methods are queries or NNS-only admin calls. All four are scoped to rkp4c-7iaaa-aaaaa-aaaca-cai (verified as "NNS Cycles Minting" against the dashboard registry) rather than matched globally, so an unrelated canister's method that happens to share a name still works.

Recovery is preserved, just not through the connector: these refusals point at the icp CLI, with the install pointer and the skill://icp-cli / skill://cycles-management guides — the same redirect the creation spends already used. The "deliberately not listed" scope note is gone from the module doc.

3. Description now matches behavior. canister_update_call's description carries your sentence verbatim:

Financial operations and update calls to known financial-service canisters are not supported and return an error.

The test that prohibited the word "financial" there is replaced by update_call_description_discloses_the_refusal, which pins the disclosure and additionally asserts the description names no venue. The full policy — refused method families and the reason — stays in the server-level instructions rather than being restated per tool; the point of the old split was to avoid a policy paragraph reading as a hint, and one factual sentence doesn't. OpenAI's "side effects should never be hidden or implicit" is the clearer argument here than the one the old test encoded.

4. Venue names removed (the risk-reduction change). Adopted. Every refusal, the server instructions, the README, the landing page, and the submission docs now say the operation belongs outside the connector, in a trusted interface the user controls. Nothing names a wallet. Two related cleanups: the discover_app_canisters description's example domain was a wallet — it's now opencloud.org; and the neutral-wording test asserts the refusal contains no .com and no "wallet", so this can't quietly regress.

Canister creation and funding keep the icp CLI pointer, on the reasoning that it's the user's own tooling rather than a transactional venue — and your point 2 asks for exactly that pointer for the recovery path. Say the word if you'd rather those went neutral too.

Tests: 153 core (up from 151) + 52/10/9/20/1, all green; clippy at the repo's 10-warning baseline.


Generated by Claude Code

Comment thread docs/openai-directory-submission.md Outdated
the cycles-minting canister's funding-completion methods on those
canisters, and every update call on a curated list of known
financial-service canisters (token ledgers and minters, exchanges, wallet
backends, staking/governance). The refusal tells the user to perform the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, let's omit " and every update call on a curated list of known
financial-service canisters (token ledgers and minters, exchanges, wallet
backends, staking/governance)."

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omitted in 1e8baa0, same as the Anthropic one: the bullet now says "every update call on the financial-service canisters it carries".


Generated by Claude Code

Two review decisions from the PR author and sea-snake.

icp_create_canister and icp_top_up_canister are gone. Both printed icp
CLI steps for operations that spend the user's ICP or cycles, and both
already sat on the unserved protocol router, so no client sees a change
— but the crate no longer carries a funding-shaped tool at all, which is
what the submission docs already claim. Their instruction builders,
argument and output types, and the ICP decimal helpers that existed only
to validate the amounts they echoed go with them; the two tool-surface
counts move from 26/15 to 24/13.

canister_update_call's description loses the financial sentence, per
sea-snake: a policy paragraph inside that description reads as a hint
that the tool is usable for financial transactions, which is the one
thing it must not suggest. The test that required the sentence is
replaced by the stronger property it displaced — NO tool description
carries financial language, checked across the whole served surface,
alongside the venue-naming ban. The policy stays where it belongs, in
the server-wide instructions.

Creating and funding canisters remains refused at the guard: the cycles
ledger's creation spends and the cycles-minting canister's whole update
surface, each pointing at the user's own icp CLI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 13:50

aterga commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

We should drop the two CMC functions as well.

Read as the two funding toolsicp_create_canister and icp_top_up_canister — since the two CMC notification methods (notify_create_canister, notify_top_up) were already refused by the guard in 48002b5. Done in 2fe9274.

Both tools printed icp CLI steps for operations that spend the user's ICP or cycles, and both already sat on the unserved protocol router, so no client sees a behavior change. What changed is that the crate no longer carries a funding-shaped tool at all — which is what the submission docs have been claiming ("the connector has no funding or management tools"); until now that was true of the served surface rather than of the code. Their instruction builders, argument and output types, and the ICP decimal helpers that existed only to validate the echoed amounts went with them, so nothing is left dead behind. Tool-surface counts move 26 → 24 across both halves, 15 → 13 on the protocol half.

Creating and funding a canister is still refused at the guard, unchanged: the cycles ledger's create_canister/create_canister_from spends and the cycles-minting canister's whole update surface (notify_top_up, notify_create_canister, notify_mint_cycles, create_canister), each refusal pointing at the user's own icp CLI, which is also how an interrupted mint is recovered.

The same commit drops the financial sentence from canister_update_call's description per @sea-snake, replacing the assertion that required it with a check that no served tool description contains financial language.

Green locally: 143 core + 20 local tests, clippy at its 10-warning baseline.


Generated by Claude Code

aterga pushed a commit that referenced this pull request Aug 28, 2026
Resolves two conflicts in tools.rs against this branch's metadata work:

- canister_update_call keeps this branch's factual description, minus
  the financial sentence #163 has now removed from every description.
- The two instructions-only tool tests go with the tools they covered;
  this branch's model_readable_metadata_states_capabilities_not_directives
  test stays, and now runs over the 11-tool served surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Suppressed comments (1)

crates/imcp2-core/src/tools.rs:531

  • This integration comment still describes only the ICRC and system-canister method rules, omitting both new scopes: global manage_neuron refusal and blanket refusal of every update on listed finance canisters. Update it so future changes do not treat this call site as a narrower method-only guard.
        // system ledgers'/cycles-minting canister's own value-moving methods
        // on those canisters, before any network work, pointing the user
        // outside this connector. Queries need no gate — a query cannot
        // commit state, so it cannot move funds.

Comment thread crates/imcp2-core/src/tools.rs Outdated
Comment on lines +1952 to +1957
/// financial-transactions policy is stated HERE in full, server-wide, because
/// it governs the whole surface rather than one tool; `canister_update_call`'s
/// own description carries a one-sentence disclosure of it, so the description
/// matches the tool's actual behavior (both directories require that, and a
/// refusal is a side effect a caller must be able to see from the description
/// alone). Neither surface names a venue for a refused operation.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — that comment described the design that had just been reversed. Fixed in 2d8e5e6: it now says the policy is stated server-wide and in no tool description, with the reason (a policy paragraph in that description reads as a hint the tool is usable for financial transactions) and the name of the test that holds the line across every served description.

The three documentation claims you flagged in the same review — README, and both submission docs — were the same staleness and went out in 1e8baa0, which your review raced. None of them now asserts a tool-level disclosure.


Generated by Claude Code

Comment thread README.md Outdated
| `get_canister_api_doc` | `canister_id` | The canister's own prose API guide ("how this app behaves" — units, auth, lifecycle, mutation safety, polling, gotchas), from its `getApiDoc`/`get_api_doc` method. Call **only** when `get_canister_candid`/`open_app` report `api_doc_available`. Returns a **structured** result in every case — `available` + the doc on success, else `available:false` with `expected`/`retry`/`next` so an expected absence is distinct from an unreachable canister |
| `canister_query` | `canister_id`, `method?` **or** `oql?`, `args?` (textual Candid), `derivation_origin?`, `account?`, `candid?` | READ a canister — provide EITHER a Candid `query` `method` (with `args`) OR an `oql` query (a JSON object string, run against `execute`). A Candid `method` query may be anonymous or as your account and returns textual Candid; an `oql` query **requires** `derivation_origin` and returns `columns` + `rows` (a table) with `has_more`, validating `start` against the schema on an empty result. On an OQL canister a Candid `method` query is rejected — use `oql`. `candid` is a fallback: the `.did` interface text to encode/decode against when the canister exposes no `candid:service` metadata. Echoes `derived_for_origin` / `requested` / `acted_as_principal` |
| `canister_update_call` | `canister_id`, `method`, `args` (textual Candid), `derivation_origin?`, `account?`, `candid?` | Make an UPDATE (state-changing) call; reply as textual Candid; anonymous, or as your account at an app (identified by its canonical II `derivation_origin`, obtained once from `open_app`/`resolve_app`). **Financial transactions are refused**: the ICRC-standard transfer/approval methods (ICRC-1/ICRC-2 and the ICRC-4/-7/-37 equivalents) are disallowed on every canister, and the ICP and cycles ledgers' own value-moving methods (the legacy `transfer`, `withdraw`, the `create_canister` spends) on those ledgers, to protect the user — the refusal directs the user to act themselves — in a wallet they control (e.g. [oisy.com](https://oisy.com)), or, for canister creation, with the [icp CLI](https://github.com/dfinity/icp-cli) in their own terminal. `candid` is the same `.did` fallback as on `canister_query`, used when the interface isn't published on-chain. Echoes `derived_for_origin` / `requested` / `acted_as_principal` |
| `canister_update_call` | `canister_id`, `method`, `args` (textual Candid), `derivation_origin?`, `account?`, `candid?` | Make an UPDATE (state-changing) call; reply as textual Candid; anonymous, or as your account at an app (identified by its canonical II `derivation_origin`, obtained once from `open_app`/`resolve_app`). **Financial transactions are refused**: the ICRC-standard transfer/approval methods (ICRC-1/ICRC-2 and the ICRC-4/-7/-37 equivalents) and the NNS/SNS governance method `manage_neuron` (neuron staking and disbursement) are disallowed on every canister, and the ICP and cycles ledgers' own value-moving methods (the legacy `transfer`, `withdraw`, the `create_canister` spends) and the cycles-minting canister's funding-completion methods (`notify_top_up`, `notify_create_canister`, `notify_mint_cycles`, `create_canister`) on those canisters; and **every** update call is refused on a curated list of known financial-service canisters (token ledgers and minters, exchanges, wallet backends, staking/governance) — all to protect the user. The refusal directs the user to perform the operation outside the connector, in a trusted interface they control — or, for canister creation and funding, with the [icp CLI](https://github.com/dfinity/icp-cli) in their own terminal. The tool's own description states that financial operations and update calls to known financial-service canisters are not supported and return an error. `candid` is the same `.did` fallback as on `canister_query`, used when the interface isn't published on-chain. Echoes `derived_for_origin` / `requested` / `acted_as_principal` |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1e8baa0 (your review raced the push). The row now ends "The policy is stated in the server-level instructions, deliberately not in any tool description." — matching the test at tools.rs:2514-2521, which is the direction the maintainers settled on.


Generated by Claude Code

Comment thread docs/anthropic-directory-submission.md Outdated
Comment on lines +167 to +171
user-run icp CLI). The policy is stated in full in the server-level
instructions, and `canister_update_call`'s own description discloses that
financial operations and update calls to known financial-service canisters
are not supported and return an error — so the description matches the
behavior.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1e8baa0. The passage now states the observable posture: the policy is in the server-level instructions — the field the directories scan — and deliberately in no tool description, held there by a test across the served surface. Nothing in the document claims a disclosure a reviewer would not find.

The equivalent claim in the OpenAI doc went out in the same commit.


Generated by Claude Code

Comment thread docs/openai-directory-submission.md Outdated
Comment on lines +129 to +135
- **The descriptions match the behavior**, as the guidelines require ("tools
should behave exactly as their names, descriptions, and inputs indicate";
"side effects should never be hidden or implicit"):
`canister_update_call`'s description states that financial operations and
update calls to known financial-service canisters are not supported and
return an error, and the full policy — refused method families and the
reason — is in the server-level instructions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1e8baa0. The attestation bullet no longer claims a tool-level disclosure: it says every description states what its tool does, returns, and rejects, and that the financial-transactions policy is stated in full in the server-level instructions — the field the scan reads — and kept out of descriptions deliberately.


Generated by Claude Code

@@ -533,7 +538,6 @@ struct KnownApp {
}

const KNOWN_APPS: &[KnownApp] = &[

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inconsistency is real, so I've documented the actual criterion rather than invent a principled one — but the choice of which way to make it consistent isn't mine, so flagging it rather than acting.

What's true: name resolution is a read convenience. It turns a name into an app URL and derivation origin so open_app can read interfaces, discover canisters, and derive the user's per-app principal. It confers no ability to act — this PR's guard refuses every update call to all three of those apps' canisters, Oisy and MULTI/DEX and ICPSwap alike — so an entry here routes to reads, not to a transaction. That holds equally for NNS, which is why keeping its derivation origins was safe and correct.

So there is no safety distinction, and I won't pretend otherwise: NNS came out at the author's request, an editorial choice about which names the server advertises. 2d8e5e6 says exactly that at the list.

The consistent alternative you're pointing at — apply the financial-app criterion to the rest — would empty KNOWN_APPS entirely, since all three remaining entries are financial services. That deletes name resolution as a feature and makes open_app("oisy") fail for a legitimate read. That's a product decision for @aterga, not something to slip into a compliance PR.


Generated by Claude Code

…closes

Two review points from sea-snake: the submission docs and the README
described the finance-canister rule as covering "a curated list" and then
enumerated the categories, which invites the reading that some services
are outside it. They now say the guard refuses every update call on the
financial-service canisters it carries, with no hedge.

The same passages still claimed canister_update_call's description
discloses the financial refusal, which stopped being true when that
sentence came out. They now state the actual posture: the policy is in
the server-level instructions — the field the directories scan — and
deliberately in no tool description, held there by a test across the
served surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 13:55
…rion

The SERVER_INSTRUCTIONS doc comment still described the design that was
just reversed: it said canister_update_call's description carries a
one-sentence disclosure. It now says the policy is server-wide and in no
tool description, and names the test that holds that.

KNOWN_APPS says what it is and why its contents are safe: name
resolution is a read convenience — the guard refuses every update call to
all three apps' canisters, so an entry routes to reads, not to a
transaction. NNS came out at the author's request, which was a choice
about which names the server advertises rather than a safety criterion,
and its derivation origins stay so reads still resolve to the right
identity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

crates/imcp2-core/src/tools.rs:1957

  • This says canister_update_call contains a financial-policy disclosure, but its description at line 506 contains none, and financial_policy_is_a_server_instruction_not_a_description explicitly enforces that omission. Correct this comment so it does not document the opposite contract.
/// governs the whole surface rather than one tool — and deliberately in NO
/// tool description (per review): a policy paragraph inside
/// `canister_update_call`'s description reads as a hint that the tool is
/// usable for financial transactions, which is the one thing it must not
/// suggest. `financial_policy_is_a_server_instruction_not_a_description`

crates/imcp2-core/src/compliance.rs:69

  • The canister_update_call description does not disclose this policy; tools.rs:2513-2522 tests that no served tool description contains financial wording. Align this module documentation with the enforced server-instructions-only design.
//!     instructions (get_info) and disclosed in `canister_update_call`'s own
//!     description; this guard enforces it for the standardized

crates/imcp2-core/src/tools.rs:531

  • This integration comment still describes only the ICRC and system-canister rules, omitting the new global manage_neuron rule and the finance-canister blanket. That makes the guard look narrower than the call directly below actually is. Document all three scopes here.
        // system ledgers'/cycles-minting canister's own value-moving methods
        // on those canisters, before any network work, pointing the user
        // outside this connector. Queries need no gate — a query cannot
        // commit state, so it cannot move funds.

Comment thread docs/openai-directory-submission.md Outdated
Comment on lines +128 to +136
- **The descriptions match the behavior**, as the guidelines require ("tools
should behave exactly as their names, descriptions, and inputs indicate";
"side effects should never be hidden or implicit"):
every tool description says what its tool does, what it returns, and what
it rejects. The financial-transactions policy is not restated there: it is
stated in full in the server-level instructions, which is the field the
scan reads, and kept out of the descriptions deliberately — a policy
paragraph inside `canister_update_call`'s description would read as a hint
that the tool is usable for financial transactions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair hit on my own replacement text — as written, the bullet asserted "every description says what it rejects" and then conceded the financial rejection isn't among them, which reads as a contradiction rather than a distinction. Fixed in dedf749.

It now separates the two claims, because they are about different things:

  • each description states what its tool does, what it returns, and which inputs it rejects (an anonymous OQL read, a Candid data query on an OQL canister, a URL with no Internet-Computer evidence);
  • the financial-transactions policy is server-wide, not per-tool, and is stated once in the server-level instructions — the field the scan reads — and deliberately in no description.

So nothing promises a behavior the tool lacks, and no refusal is hidden; it is stated for the whole surface in one place. The same commit also cleared the two remaining stale claims your suppressed comments named: the module doc in compliance.rs and the gate's call-site comment (which additionally now documents all three scopes rather than just the method rules).

On the third suppressed comment — tools.rs:1957 — that one is a misread: the text it quotes is the corrected version, which says the policy is stated "deliberately in NO tool description". Nothing to change there.


Generated by Claude Code

Copilot AI review requested due to automatic review settings August 28, 2026 14:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

crates/imcp2-core/src/compliance.rs:69

  • This scope note contradicts the implemented metadata contract: canister_update_call has no financial-policy disclosure, and tools.rs:2504-2530 explicitly tests that the policy exists only in server instructions. Remove the tool-description claim so the module documentation matches the enforced design.
//!     instructions (get_info) and disclosed in `canister_update_call`'s own
//!     description; this guard enforces it for the standardized

crates/imcp2-core/src/tools.rs:531

  • The updated guard comment still describes only the ICRC and system-canister branches, omitting both new behaviors: global manage_neuron rejection and blanket rejection for listed finance canisters. Document all three scopes here so future changes at this call site do not rely on an incomplete description of the gate.
        // system ledgers'/cycles-minting canister's own value-moving methods
        // on those canisters, before any network work, pointing the user
        // outside this connector. Queries need no gate — a query cannot
        // commit state, so it cannot move funds.

…tale claims

The comment above the gate in canister_update_call still described a
method-only guard, which makes the call look narrower than it is. It now
names all three scopes: the standardized value-moving names (the ICRC
surface plus manage_neuron) on every canister, the system ledgers' and
cycles-minting canister's own methods on those canisters, and every
update method on a listed financial-service canister.

The compliance module doc still said the policy is disclosed in
canister_update_call's description. It now says the opposite, with the
reason.

The OpenAI submission's descriptions-match bullet claimed every
description says what it rejects and then said the financial rejection is
absent from them — a contradiction a reviewer would catch. It now
distinguishes the two: descriptions state the inputs each tool rejects,
and the financial policy is a server-wide statement made once, where the
scan reads it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 14:05
aterga pushed a commit that referenced this pull request Aug 28, 2026
One conflict, in SERVER_INSTRUCTIONS: this branch's factual instruction
text is kept, and its doc comment takes #163's correction — the policy is
stated server-wide and in no tool description, held there by a test that
now also covers the schemas.

The instruction text itself loses the same hedge sea-snake asked to
remove from the docs: it said "a curated list of known financial-service
canisters", which invites the reading that some services are outside the
list. It now says the financial-service canisters the guard carries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

"{}: {desc}",
tool.name
);
assert!(!desc.contains(".com"), "{} names a venue: {desc}", tool.name);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this one rather than taking it at face value, and it doesn't hold: icp_find_app_by_name is not a served tool, so the assertion never sees that description.

  • It is declared at line 1327, inside impl IcProtocolTools (which opens at line 1272) — the deferred half.
  • The test iterates IcTools::all_tools(), which is IcCanisterTools::tool_router().list_all() (line 134) — the served half only, lines 157–1269.
  • the_default_composition_defers_the_protocol_tools pins that boundary: 11 served tools, none icp_-prefixed except icp_oql_guide.

Empirically: cargo test -p imcp2-core --lib financial_policy_is_a_server_instruction_not_a_description passes on dedf749, and CI's test job is green on that head — so the workspace-green report stands.

The <name>.com/.app placeholder is also not a venue in the sense the check targets: the rule exists so metadata answering a refused financial operation doesn't hand the model another transactional service, and that string is a lookalike-domain example inside an unserved description.

One real note from this, which I'm not acting on inside this PR: if IcProtocolTools is ever wired back into the served surface, this check won't extend to it automatically, and that placeholder would then need rewording. Worth handling in whichever change re-serves that half.


Generated by Claude Code

Comment thread docs/openai-directory-submission.md Outdated
stated where the scan reads it: in full in the server-level instructions,
and deliberately in no description — a policy paragraph inside
`canister_update_call`'s description would read as a hint that the tool is
usable for financial transactions. So no description promises a behavior

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and deliberately in no description — a policy paragraph inside
canister_update_call's description would read as a hint that the tool is
usable for financial transactions

Why did you mention this here 😭😭😭

Please omit this for the love of god!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, and the reason is worth stating plainly: explaining why the policy is kept out of descriptions invites the reading it exists to prevent. A reviewer needs the posture, not our deliberation.

Omitted in a747610, from both documents — I took the Anthropic one out in the same commit, before your second comment arrived. Both now say the policy is stated in the server-level instructions, covering the whole surface at once, held there by a test, and nothing further.

I did keep the rationale in the two code comments (tools.rs, compliance.rs), since that is what stops the sentence being added back a third time and directory review never reads them. Say so if you want those trimmed as well.


Generated by Claude Code

Comment thread docs/anthropic-directory-submission.md Outdated
outside the connector, in a trusted interface they control, and names no
venue (a refused canister-creation or funding-completion call points at the
user-run icp CLI). The policy is stated in full in the server-level
instructions — the field the directories scan — and deliberately in no tool

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

— and deliberately in no tool
description: a policy paragraph inside canister_update_call's description
would read as a hint that the tool is usable for financial transactions.

Same as in my other comment, please omit for the love of god!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already out — a747610 removed it from this document and the OpenAI one together, since the sentence was the same in both. This bullet now ends: the policy is stated in the server-level instructions, the field the directories scan, where it covers the whole surface at once, held there by a test.


Generated by Claude Code

Both directory documents explained why the financial policy is kept out
of tool descriptions. A reviewer does not need the deliberation, and
spelling it out invites the reading it exists to prevent — that the tool
might otherwise be usable for financial transactions. They now state the
posture: the policy is in the server-level instructions, covering the
whole surface at once, held there by a test.

The same rationale stays in the code comments (tools.rs, compliance.rs),
where it is the reason the test exists and the thing that stops the
sentence being added back a third time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 14:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread crates/imcp2-core/src/discover.rs Outdated
Comment on lines +542 to +549
// canisters, and derive the user's per-app principal. It confers no ability to
// act — every update call to these apps' canisters is refused by
// [`crate::compliance`], which carries all three of them — so an entry here is
// discovery-neutral rather than a route to a transaction. NNS was dropped from
// this list at the author's request; that was an editorial choice about which
// names the server advertises, not a safety criterion, and its derivation
// origins are deliberately kept below so reads still resolve to the right
// identity.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and it stings a little: that was the same overclaim this PR keeps removing from other people's sentences, in a comment I wrote two commits ago. The list covers each service's central canisters, and compliance.rs:73-78 says plainly that a static list cannot cover an exchange's dynamically created pool canisters — so "every update call to these apps' canisters is refused" was wrong.

Fixed in 27a2cc8. It now says name resolution writes nothing, so an entry is not itself a route to a transaction; a later update call is a separate request and goes through the guard under exactly the scope that module documents — including its note on what the list cannot cover. No claim of complete canister coverage.


Generated by Claude Code

The comment justifying KNOWN_APPS said every update call to those apps'
canisters is refused. That is the overclaim this PR keeps removing
elsewhere: the list covers each service's central canisters, and
compliance.rs says in its own scope notes that a static list cannot cover
an exchange's dynamically created pool canisters.

What is true, and what it says now: name resolution writes nothing, so an
entry is not itself a route to a transaction; a later update call is a
separate request and goes through the guard under exactly the scope that
module documents, including its note on what the list cannot cover.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvwAVXfx5kLNc4SqKXkavk
Copilot AI review requested due to automatic review settings August 28, 2026 14:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

crates/imcp2-core/src/management.rs:37

  • Removing E8S_PER_ICP leaves its doc comment attached to MAX_SINGLE_SHOT_WASM, so the generated documentation now incorrectly describes the Wasm-size threshold as an ICP conversion constant. Remove the orphaned line.
/// 1 ICP = 100_000_000 e8s.

crates/imcp2-core/src/tools.rs:2478

  • The instruction-only tools were removed from this array, but their explanatory comment remains and now annotates no entries. Remove it so the read-only classification test does not imply that any listed tool is instruction-only.
            // Instructions-only since the marketplace-compliance changes: they
            // execute nothing and move no funds, so they are pure reads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants