mcp server
KakoroPay
an MCP server plus a Soroban contract that lets an LLM agent autonomously discover a paid resource and settle payment, with the contract enforcing an AI-generated spend policy (rate limits, allowed ca
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 22, 2026AgentPay
An AI agent discovers, authorizes, pays for, and calls on-chain resources — with spending policies generated from data and enforced by a Soroban smart account.
Repo: github.com/AIonWeb3/AgentPay
AgentPay targets two Stellar Community Fund RFPs:
- AI-Assisted Policy Toolkit — Turns observed/simulated transactions into a minimal least-privilege account policy (spending caps + contract allowlists).
- MCP Discovery & Paid-Call Server — Lets an AI agent find and pay for a resource from inside its own runtime via the Model Context Protocol.
Pitch demo
A local operator console walks the full story on one screen: synthetic traffic → policy → MCP discover → budget check → approved pay → policy deny → per-vendor scope.
./scripts/run_pitch.sh
# or:
pip install -r demo/requirements.txt -r policy-generator/requirements.txt
python scripts/seed_pitch.py
python demo/server.py
Open http://127.0.0.1:8080, go fullscreen, click Run pitch demo.
The console is a FastAPI app plus a vanilla HTML/CSS/JS UI. It persists session,
policy, rules, audit events, and the marketplace registry in SQLite. Mutating
routes require DEMO_API_KEY; read routes accept that key or DEMO_READ_KEY.
Operator UI covers:
- Stepped pitch API (
POST /api/pitch/step) with a live narration strip - MCP-style tools: discover, check_budget, pay_and_call (weather / price / inference)
- Policy and marketplace cards, per-vendor remaining spend and call budget
auth_decisionaudit timeline and loading / error toasts- Empty and reset confirmation states, keyboard and screen-reader labels
- Responsive layout; export of the simulation log (
GET /api/tx-log)
Simulated vs on-chain: the console enforces the same allowlist, spend cap,
and rate-limit rules as contracts/agent-account, with deterministic local tx
hashes. The MCP server talks to live Soroban RPC / stellar contract invoke
when ACCOUNT_CONTRACT_ID and STELLAR_IDENTITY are set (see .env.example).
Optional AgentGuard: set AGENTGUARD_CONTRACT_ID and AGENTGUARD_REQUIRED_ROLE
(Basic / Premium / Admin) so __check_auth calls verify_agent before
spend effects.
Without those, check_budget falls back to AGENTPAY_STATE and pay_and_call
returns a local_ hash — never a stub success against a configured contract.
Copy .env.example if you change keys (DEMO_API_KEY, DEMO_READ_KEY,
DATABASE_URL, AGENTGUARD_CONTRACT_ID). The demo store uses DATABASE_URL
(default sqlite:///demo/data/agentpay.db). The MCP server can read a JSON
budget snapshot from AGENTPAY_STATE when set.
Local CI
./scripts/ci.sh
Gates: cargo fmt, clippy -p mcp-server, cargo test --workspace, ruff, pytest.
GitHub Actions (.github/workflows/ci.yml) runs the same Rust and Python jobs
on every push and pull request.
Python tests live in tests/, policy-generator/, and demo/tests/ (engine,
auth, persistence, pitch API, UI smoke, accessibility, and full agent-pay flow).
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ AI Agent Runtime │
│ │
│ ┌──────────┐ MCP/stdio ┌──────────────────────────────┐ │
│ │ AI Agent │◄──────────────►│ MCP Server (rmcp) │ │
│ │ │ │ • discover_resources(query) │ │
│ └──────────┘ │ • check_budget() │ │
│ │ • pay_and_call(id, params) │ │
│ └──────────┬───────────────────┘ │
└──────────────────────────────────────────┼───────────────────┘
│ Soroban RPC (when ACCOUNT_CONTRACT_ID is set)
▼
┌────────────────────────┐
│ Stellar Testnet │
│ │
│ ┌──────────────────┐ │
│ │ Agent Account │ │
│ │ (Smart Account) │ │
│ │ │ │
│ │ Context Rules │ │
│ │ Spending Limits │ │
│ │ AgentGuard check │ │
│ │ Audit Events │ │
│ └──────────────────┘ │
└────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Policy Generation Pipeline │
│ │
│ Transaction Log ──► generate_policy.py ──► PolicySpec JSON │
│ (observed data) (p95 caps + allowlist) (apply on-chain) │
│ │
│ simulate_agent.py ──► synthetic log for demos │
│ seed_pitch.py ──► deterministic 75-tx seed + policy JSON │
│ demo/server.py ──► visual operator console │
└─────────────────────────────────────────────────────────────────┘
Components
| Component | Language | Description |
|---|---|---|
contracts/agent-account/ | Rust (Soroban) | Smart account: context rules, spend/rate policy, optional AgentGuard verify_agent |
mcp-server/ | Rust | MCP server with 3 tools: discover, check_budget, pay_and_call |
policy-generator/ | Python | Rule-based policy generator (p95 × 1.5 caps from tx logs) |
demo/ | Python + HTML | Pitch console: HTTP API, SQLite store, in-memory policy engine |
registry/ | JSON | Seed data for paid resource discovery (3 vendors) |
scripts/ | Bash/Python | Pitch seed, local CI, testnet deploy, synthetic tx logs |
tests/ | Python | Repo-level checks (CI config, env, README, rustfmt) |
Quick Start
Prerequisites
- Rust 1.84+ with
wasm32v1-nonetarget - Stellar CLI
- Python 3.10+ (CI uses 3.12)
1. Build & Test the Smart Account
cargo test -p agent-account
2. Run the MCP Server
cargo run -p mcp-server
The server starts on stdio. Tools take real arguments (query, resource_id,
params). Connect any MCP-compatible client to use them.
3. Generate a Policy (Python)
pip install -r policy-generator/requirements.txt
python scripts/simulate_agent.py > transaction_log.json
python policy-generator/generate_policy.py transaction_log.json > policy.json
End-to-End Demo Flow
1. SIMULATE → python scripts/simulate_agent.py > tx_log.json
Generates 75 synthetic transactions across 3 resources.
2. GENERATE → python policy-generator/generate_policy.py tx_log.json > policy.json
Produces a PolicySpec with per-contract spend caps derived
from the p95 of observed amounts.
3. DEPLOY → ./scripts/deploy_testnet.sh
Simulates a tx log, generates PolicySpec, deploys the account
and spend-policy instances, initialize, set_spend_policy,
optional set_agent_guard (if AGENTGUARD_CONTRACT_ID is set),
apply_policy. Prints MCP env and stellar event commands.
4. DISCOVER → Agent calls discover_resources("weather") via MCP
Gets back matching resources with pricing info.
5. CHECK → Agent calls check_budget() via MCP
Sees remaining allowance under current policy.
6. PAY+CALL → Agent calls pay_and_call("weather-oracle", "{}") via MCP
Transaction authorized by smart account, spend recorded,
resource invoked, real tx hash when ACCOUNT_CONTRACT_ID is set.
7. AUDIT → stellar events --id <CONTRACT> (auth_decision)
Approved decisions persist on-chain; denied auths fail the tx
with OverBudget / RateLimited / InvalidContext /
AgentGuardExecutionDenied.
Steps 1–2 and 4–6 can be shown in one take via python demo/server.py
(or ./scripts/run_pitch.sh, which seeds demo/data/ first).
Project Structure
AgentPay/
├── Cargo.toml
├── pyproject.toml # ruff + pytest
├── .github/workflows/ci.yml
├── contracts/agent-account/ # Soroban smart account (+ AgentGuard client)
├── mcp-server/ # MCP tools over stdio
├── policy-generator/ # PolicySpec from tx logs
├── demo/ # Pitch console
│ ├── server.py # FastAPI routes
│ ├── engine.py # Enforcement mirroring the contract
│ ├── store.py / schema.sql # SQLite persistence
│ ├── auth.py # Operator vs reader keys
│ ├── policy_eval.py / txhash.py
│ ├── static/ # Operator UI
│ └── tests/ # API, engine, and UI smoke tests
├── registry/resources.json
├── scripts/
│ ├── run_pitch.sh
│ ├── seed_pitch.py
│ ├── ci.sh
│ ├── deploy_testnet.sh
│ └── simulate_agent.py
├── tests/
└── README.md
Tech Stack
- Soroban Contracts:
soroban-sdk,#![no_std] - Smart Account Framework: OpenZeppelin
stellar-accounts0.7.x - MCP Server:
rmcp3.1.x, stdio transport - Policy Generator: Python 3.10+,
pydantic2.x - Pitch console: FastAPI + SQLite + vanilla HTML/CSS/JS
Current Status
- Smart account: initialize, set_spend_policy, apply_policy (per-vendor
CallContractrules + spend/rate policy on__check_auth), optionalset_agent_guard(verify_agentbefore spend), get_remaining_budget, rolling window, events - MCP: discover; check_budget from on-chain account when
ACCOUNT_CONTRACT_IDis set (elseAGENTPAY_STATE); pay_and_call submits via Stellar CLI + pollsgetTransaction(no stub hash on the live path); bounded retry onTransientErroronly - Policy generator: p95 × 1.5 caps + allowlist; empty logs rejected
- Demo console: SQLite persistence, operator/reader keys, stepped pitch API, per-vendor budget, deterministic tx hashes, tx-log export, polished operator UI (responsive, a11y, toasts, loading, empty/reset)
- Deploy:
./scripts/deploy_testnet.shruns simulate → generate → deploy two instances → initialize → apply_policy; links AgentGuard whenAGENTGUARD_CONTRACT_IDis set (AGENTGUARD_REQUIRED_ROLE, default Basic) - CI: local
scripts/ci.shand GitHub Actions (fmt, clippy, cargo test, ruff, pytest)
Out of scope for this MVP (follow-up)
- Funded testnet deploy inside CI
- LLM-based policy generation
- Integration tests against public testnet in CI
License
See LICENSE.