The COTI MCP Server MCP server exposes tools that can move money, delete data, or destroy resources. Without policy enforcement, an autonomous agent has unrestricted access to every one of them.
Financial operations (transfer_native, transfer_private_erc20, transfer_private_erc721) can move real money. An agent caught in a loop could drain accounts before anyone notices.
Write operations (approve_erc20_spender, approve_private_erc721, call_contract_function) modify state. Without rate limits, an agent can make hundreds of changes in seconds -- faster than any human can review or revert.
Execute tools (compile_and_deploy_contract, compile_contract, deploy_private_erc20_contract) trigger processes with side effects. Builds, notifications, workflows -- all fired without throttling.
These COTI MCP Server tools can modify, create, or destroy resources. Without a policy, your agent has unrestricted access to all of them.
approve_erc20_spender Approve another address to spend tokens on behalf of the owner. This is used for allowing another address (like a contract) to transfer your tokens. Requires token contract address, spender address, and amount as input. Returns the transaction hash upon successful approval. Write approve_private_erc721 Approve an address to transfer a specific private ERC721 NFT token on the COTI blockchain. This allows the approved address to transfer the specified NFT on behalf of the owner. Requires token contract address, token ID, and spender address as input. Returns the transaction hash upon successful approval. Write call_contract_function Call any function on a smart contract on the COTI blockchain. Supports both read-only (view/pure) functions and state-changing (write) functions. Read-only functions return data without creating a transaction. State-changing functions create transactions and may require gas_limit. Returns the function result in a human-readable format. Write create_account Create a new COTI account with a randomly generated private key and AES key. Returns the new account details for the AI assistant to track in conversation context. The AI should remember these credentials for use in subsequent operations. Write generate_aes_key Generate or recover an AES key for a COTI account. Requires the account to be funded. The AI assistant should track the returned AES key for use in private transactions. Write import_account_from_private_key Import a COTI account using only a private key. The public key will be derived automatically, and the AES key placeholder will be set (fund the account to generate a real AES key). Write send_private_message Send an encrypted message to a specific recipient address on a deployed PrivateMessage contract. The message is encrypted using COTI MPC so only the recipient can decrypt it with their own AES key. Requires the contract address and ABI returned by deploy_private_message_contract. Write set_private_erc721_approval_for_all Approve or revoke an operator to transfer all private ERC721 NFT tokens on the COTI blockchain. This allows the operator to transfer any NFT owned by the caller in this collection. Requires token contract address, operator address, and approval status as input. Returns the transaction hash upon successful approval setting. Write switch_network Switch between COTI testnet and mainnet networks. The AI assistant should remember this network selection and pass it to subsequent blockchain operations. Returns the new network to be tracked by the AI. Write transfer_native Transfer native COTI tokens to another wallet. This is used for sending COTI tokens from your wallet to another address. Requires private key, recipient address, and amount in Wei as input. The AI assistant should track and pass the account private key from context. Returns the transaction hash upon successful transfer. Financial transfer_private_erc20 Transfer private ERC20 tokens on the COTI blockchain. This is used for sending private tokens from your wallet to another address. Requires token contract address, recipient address, and amount as input. Returns the transaction hash upon successful transfer. Financial transfer_private_erc721 Transfer a private ERC721 NFT token on the COTI blockchain. This is used for sending a private NFT from your wallet to another address. Requires token contract address, recipient address, and token ID as input. Returns the transaction hash upon successful transfer. Financial compile_and_deploy_contract Compiles Solidity source code and immediately deploys it to the COTI blockchain in a single operation. This tool avoids bytecode truncation issues that can occur when passing large bytecode strings between tools. Accepts full Solidity source code, compiles it, and deploys the result. Returns the contract address, transaction hash, and ABI (for future interactions). This is the recommended tool for most deployment scenarios. Execute compile_contract Compiles Solidity source code without deploying it to the blockchain. Returns bytecode, ABI, and compilation metadata (compiler version, EVM version, optimization settings). Useful for: - Testing that a contract compiles without errors - Getting the ABI for contract interaction - Analyzing bytecode size and structure - Preparing compilation metadata for later deployment or verification - Debugging compilation issues in isolation Execute deploy_private_erc20_contract Deploy a new standard private ERC20 token contract on the COTI blockchain. This creates a new private token with the specified name, symbol, and decimals. Returns the deployed contract address upon successful deployment. Execute deploy_private_erc721_contract Deploy a new standard private ERC721 NFT contract on the COTI blockchain. This creates a new private NFT collection with the specified name and symbol. Returns the deployed contract address upon successful deployment. Execute deploy_private_message_contract Deploys the PrivateMessage contract on the COTI blockchain. This contract allows sending encrypted messages to specific addresses. Only the intended recipient can decrypt a message using their own AES key. Returns the contract address and ABI needed for send_private_message and read_private_message. Execute These rules are based on the tool categories exposed by the COTI MCP Server MCP server. Adjust the limits to match your use case.
transfer_native:
rules:
- action: deny
on_deny: "Financial operations require approval" Financial tools should be explicitly enabled per use case, not open by default.
approve_erc20_spender:
rules:
- name: "write-rate-limit"
rate_limit: 30/hour
on_deny: "Write rate limit reached" Prevents bulk unintended modifications from agents caught in loops.
decode_event_data:
rules:
- action: allow
rate_limit: 60/minute Controls API costs and prevents retry loops from exhausting upstream rate limits.
This is the complete policy file for COTI MCP Server. It lists every tool with suggested default rules. Download it, adjust the limits, and run with Intercept.
version: "1" default: "deny" tools: compile_and_deploy_contract: rules: - action: allow rate_limit: 10/hour validate: required_args: true compile_contract: rules: - action: allow rate_limit: 10/hour validate: required_args: true deploy_private_erc20_contract: rules: - action: allow rate_limit: 10/hour validate: required_args: true deploy_private_erc721_contract: rules: - action: allow rate_limit: 10/hour validate: required_args: true deploy_private_message_contract: rules: - action: allow rate_limit: 10/hour validate: required_args: true transfer_native: rules: - action: deny on_deny: "Financial operation requires approval" transfer_private_erc20: rules: - action: deny on_deny: "Financial operation requires approval" transfer_private_erc721: rules: - action: deny on_deny: "Financial operation requires approval" decode_event_data: rules: - action: allow rate_limit: 60/minute decrypt_message: rules: - action: allow rate_limit: 60/minute decrypt_value: rules: - action: allow rate_limit: 60/minute encrypt_message: rules: - action: allow rate_limit: 60/minute encrypt_value: rules: - action: allow rate_limit: 60/minute get_current_network: rules: - action: allow rate_limit: 60/minute get_current_rpc: rules: - action: allow rate_limit: 60/minute get_native_balance: rules: - action: allow rate_limit: 60/minute get_private_erc20_allowance: rules: - action: allow rate_limit: 60/minute get_private_erc20_balance: rules: - action: allow rate_limit: 60/minute get_private_erc20_decimals: rules: - action: allow rate_limit: 60/minute get_private_erc20_total_supply: rules: - action: allow rate_limit: 60/minute get_private_erc721_approved: rules: - action: allow rate_limit: 60/minute get_private_erc721_balance: rules: - action: allow rate_limit: 60/minute get_private_erc721_is_approved_for_all: rules: - action: allow rate_limit: 60/minute get_private_erc721_token_owner: rules: - action: allow rate_limit: 60/minute get_private_erc721_token_uri: rules: - action: allow rate_limit: 60/minute get_private_erc721_total_supply: rules: - action: allow rate_limit: 60/minute get_private_message_count: rules: - action: allow rate_limit: 60/minute get_private_message_senders: rules: - action: allow rate_limit: 60/minute get_transaction_logs: rules: - action: allow rate_limit: 60/minute get_transaction_status: rules: - action: allow rate_limit: 60/minute mint_private_erc20_token: rules: - action: allow rate_limit: 60/minute mint_private_erc721_token: rules: - action: allow rate_limit: 60/minute read_private_message: rules: - action: allow rate_limit: 60/minute sign_message: rules: - action: allow rate_limit: 60/minute verify_signature: rules: - action: allow rate_limit: 60/minute approve_erc20_spender: rules: - action: allow rate_limit: 30/hour approve_private_erc721: rules: - action: allow rate_limit: 30/hour call_contract_function: rules: - action: allow rate_limit: 30/hour create_account: rules: - action: allow rate_limit: 30/hour generate_aes_key: rules: - action: allow rate_limit: 30/hour import_account_from_private_key: rules: - action: allow rate_limit: 30/hour send_private_message: rules: - action: allow rate_limit: 30/hour set_private_erc721_approval_for_all: rules: - action: allow rate_limit: 30/hour switch_network: rules: - action: allow rate_limit: 30/hour
Download the policy
curl -o davibauer-coti-mcp.yaml https://raw.githubusercontent.com/policylayer/intercept/main/policies/davibauer-coti-mcp.yaml
Run Intercept in front of the server
intercept -c davibauer-coti-mcp.yaml -- npx -y @davibauer/coti-mcp
Works with any MCP client:
Every tool call is now checked against your policy before it reaches COTI MCP Server. Denied calls are blocked and logged. Allowed calls pass through with no latency impact.
Open source. One binary. Zero dependencies.
npx -y @policylayer/intercept