{
  "markdown": "# tctc-mcp\n\n[![npm version](https://img.shields.io/npm/v/tctc-mcp)](https://www.npmjs.com/package/tctc-mcp)\n\nAn MCP server exposing [ERC-7303](https://eips.ethereum.org/EIPS/eip-7303)\n(Token-Controlled Token Circulation) roles to AI agents: agents check\ntheir own on-chain permissions, and human principals grant/revoke them\nby minting/burning control tokens — no permission server required.\n\nStatus: **v0.3** — adds timed roles with gasless auto-expiry (below),\non top of v0.2's IERC7303 auto-discovery; published on npm\n([`tctc-mcp`](https://www.npmjs.com/package/tctc-mcp)), unit-tested\nand verified end-to-end against the Sepolia demo deployment (grant →\ncheck → revoke → check, and grant-for-75s → auto-expiry, through a\nreal MCP client).\n\n## Demo (60 seconds)\n\n[![Watch the 60-second demo video](docs/tctc-mcp-demo-thumb.png)](https://www.youtube.com/watch?v=o547bwYT32A)\n\n*A human grants an AI agent a minting permission; the agent verifies it\non-chain and mints an NFT. The human burns the role token — and the\nagent instantly loses the capability. Live on Sepolia, no permission\nserver involved.*\n\n## Quick start\n\nThe package is published on npm, so no clone or build is needed — `npx`\nfetches and runs it directly:\n\n```bash\n# 1. Get a config. The secret-free Sepolia demo config needs no API keys:\ncurl -fsSLO https://raw.githubusercontent.com/kofujimura/tctc-mcp/main/examples/config.sepolia.agent.json\n\n# 2. Register with your MCP client, e.g. Claude Code\n#    (read-only mode: only query tools are registered)\nclaude mcp add tctc -- npx -y tctc-mcp --config \"$PWD/config.sepolia.agent.json\"\n\n# Admin mode (principal side): grant_role / revoke_role also registered.\n# Provide the issuer key ONLY via the environment:\nclaude mcp add tctc-admin --env TCTC_ADMIN_PRIVATE_KEY=0x... \\\n  -- npx -y tctc-mcp --config \"$PWD/config.sepolia.json\"\n```\n\nOr in a project-scoped `.mcp.json`:\n\n```json\n{ \"mcpServers\": { \"tctc\": { \"command\": \"npx\",\n    \"args\": [\"-y\", \"tctc-mcp\", \"--config\", \"examples/config.sepolia.agent.json\"] } } }\n```\n\nA fuller registration example is in\n[examples/claude.mcp.json](examples/claude.mcp.json). The admin private\nkey is only ever read from the `TCTC_ADMIN_PRIVATE_KEY` environment\nvariable; configs containing anything that looks like a private key are\nrejected at startup.\n\n### Using tctc-mcp from your own app\n\nThe **only supported entry point is the `tctc-mcp` bin** — spawn it via\n`npx --no-install tctc-mcp` (or `node_modules/.bin/tctc-mcp`). Never\nreference the package's `dist/` files directly: they are internal,\ntheir layout is unversioned, and the package's `exports` field refuses\ndeep imports. A minimal MCP-SDK client example (the pattern for a web\nbackend) is in\n[examples/client-stdio.mjs](examples/client-stdio.mjs); the release\npipeline verifies the packed bin end-to-end\n([scripts/verify-pack.mjs](scripts/verify-pack.mjs)).\n\n## Web application starter\n\nWant to see `tctc-mcp` protecting a real API route?\n\n[`tctc-openai-starter`](https://github.com/kofujimura/tctc-openai-starter)\nis a standalone Next.js starter that verifies wallet ownership with\nSign-In with Ethereum, checks the configured role through `tctc-mcp`,\nand calls OpenAI only when the on-chain gate grants access.\n\nUse it as a [GitHub template](https://github.com/new?template_name=tctc-openai-starter&template_owner=kofujimura).\n\n## Token-gating any MCP server: tctc-gate\n\nThe reverse direction lives in this repo too:\n[`tctc-gate`](gate/) ([npm](https://www.npmjs.com/package/tctc-gate)) is a\ntransparent stdio proxy that puts an ERC-7303 role check in front of **any\nexisting MCP server, unmodified** — deny comes back with a grant URL that\nopens the dashboard pre-filled. tctc-mcp lets agents *ask* about roles;\ntctc-gate *enforces* them at the boundary:\n\n```sh\nnpx -y tctc-gate --config gate.json -- npx -y some-mcp-server …\n```\n\n## Tools\n\n| Tool | Mode | Purpose |\n|---|---|---|\n| `list_roles` | both | Configured roles and their control tokens |\n| `check_role` | both | Does an account hold a role? (live `balanceOf`, with evidence) |\n| `check_all_roles` | both | Session-start self-assessment across all roles |\n| `discover_roles` | both | Introspect **any** contract via `IERC7303` — no role config needed |\n| `resolve_agent` | both* | ERC-8004 `agentId` → owner / agentURI / agentWallet / ERC-6551 TBA |\n| `grant_role` | admin | Mint the control token to a subject |\n| `revoke_role` | admin | Burn the subject's control token — the kill switch |\n\n\\* registered only when the config has an `identity` section.\n\nSubjects can be given as a raw `address`, as an ERC-8004 `agentId`\n(resolved to its ERC-6551 Token Bound Account, the recommended binding\ntarget), or omitted to use the config's `self`.\n\n## IERC7303 auto-discovery (v0.2)\n\nERC-7303 now defines an introspection interface\n([ethereum/ERCs#1872](https://github.com/ethereum/ERCs/pull/1872), merged\n2026-07-11): compliant contracts expose `hasRole`, control-token getters,\nconfiguration events, and ERC-165 detection (interfaceId `0x4ee69337`).\ntctc-mcp uses it two ways:\n\n- **`target` roles** — a role config names only the target contract;\n  the server reads which control tokens gate the role *from the contract\n  itself*, and the verdict is the target's own `hasRole()` answer:\n\n  ```json\n  \"roles\": { \"MINTER_ROLE\": {\n      \"target\": { \"address\": \"0x4C0a78803D47154B9C6F42EC4AEbab2D1C94c97D\" } } }\n  ```\n\n- **`discover_roles`** — introspect any address at run time, with no\n  role configuration at all. Non-compliant contracts report\n  `supportsIERC7303: false`; static `controlTokens` configs remain the\n  fallback for pre-IERC7303 deployments.\n\nWorking example: [examples/config.sepolia.discovery.json](examples/config.sepolia.discovery.json)\n(secret-free, public RPC), verified live by `scripts/e2e-discovery.mjs`.\n\n## Timed roles: gasless auto-expiry (v0.3)\n\nDelegation to an agent is usually *short-term* — \"mint for one hour\",\n\"act for the duration of this task\". With an **expiring control token**\n([`ExpiringControlTokens`](https://sepolia.etherscan.io/address/0xb5abB6c060ed287e8B25aD121c8B46eE404fF09b#code)),\n`balanceOf()` returns 0 once the holder's expiry passes, so the role\nrevokes **by itself, with no transaction** — even if the principal\nforgets, goes offline, or loses keys. The ERC-7303 target contract\nneeds no changes at all (the Sepolia expiry demo target is a\nbyte-for-byte copy of `TCTCDemoToken`).\n\n- **Granting:** a role whose grant template has `$expiresAt` requires\n  an expiry — `grant_role` with `expiresInSeconds: 3600` is\n  \"grant MINTER_ROLE for one hour\":\n\n  ```json\n  \"admin\": { \"grant\": { \"function\": \"mint(address,uint256,uint64)\",\n                        \"args\": [\"$subject\", \"$typeId\", \"$expiresAt\"] } }\n  ```\n\n- **Checking:** `check_role` evidence reports `expiresAt` (unix\n  seconds) when the control token exposes it, so an agent can\n  self-report \"this permission expires in 5 minutes\".\n- **Kill switch unchanged:** expiry is a fail-safe, not a replacement —\n  `revoke_role` (issuer burn) still revokes immediately within the\n  validity window.\n\nWorking example: the `TIMED_MINTER_ROLE` in\n[examples/config.sepolia.json](examples/config.sepolia.json), verified\nlive by `scripts/e2e-expiry.mjs` (grant for 75 s → watch it expire with\nno further transaction).\n\n## Human dashboard\n\n**Live: <https://tctc-mcp.vercel.app/>** — while tctc-mcp exposes ERC-7303\nroles to AI agents, the [TCTC Dashboard](dashboard/) exposes the same\non-chain state to the humans who manage them: inspect any IERC7303 target,\nwatch `hasRole` verdicts and per-control-token `balanceOf` evidence live,\ngrant/revoke as the issuer (with timed grants and countdowns for expiring\ncontrol tokens), and deploy new control-token collections straight from a\nbrowser wallet. Two clients of one source of truth: the chain. See\n[dashboard/README.md](dashboard/README.md) for details and try-it links.\n\n[![TCTC Dashboard — inspecting a target's roles, with live hasRole verdicts and issuer grant/revoke controls](docs/tctc-mcp-dashboard.png)](https://tctc-mcp.vercel.app/)\n\n*Not just for AI-agent delegation: any ERC-7303 contract works, so the\ndashboard doubles as a general-purpose on-chain permission manager —\nissue certificate collections, grant and revoke roles, and audit who\nholds what, all from a browser wallet.*\n\n## Documents\n\n- [docs/CONCEPT.md](docs/CONCEPT.md) — background and rationale: TCTC as\n  the authorization layer for AI agents, its relationship to ERC-8004\n  (Trustless Agents) and ERC-6551 (Token Bound Accounts), recommended\n  ERC-7303 spec updates, and the adoption strategy.\n- [docs/MCP_SERVER_SPEC.md](docs/MCP_SERVER_SPEC.md) — v1 design\n  specification (architecture, config, tools, security, roadmap).\n- [docs/ERC_DRAFT_EXPIRABLE_1155.md](docs/ERC_DRAFT_EXPIRABLE_1155.md) —\n  working draft of a planned ERC, \"Expirable ERC-1155 Tokens\": the\n  standard behind the timed roles above (per-holder expiry, time-aware\n  `balanceOf`, `expiresAt`/`ExpiryUpdated`, interface ID `0x300e616b`).\n  Not yet submitted to ethereum/ERCs; feedback welcome.\n- [docs/TEST_REPORT.md](docs/TEST_REPORT.md) — v1 test report: 24 unit\n  tests and the live Sepolia E2E (on-chain kill-switch cycle through a\n  real MCP client).\n- [examples/config.sepolia.json](examples/config.sepolia.json) —\n  concrete config for the Sepolia demo deployment (primary roles,\n  static bindings) and the TCTC repo's `MyComplexToken` sample\n  (`COMPLEX_*` roles, resolved via IERC7303 `target` discovery).\n- [examples/config.sepolia.agent.json](examples/config.sepolia.agent.json)\n  — secret-free agent-side config for the same demo deployment (public\n  RPC, no API keys); the one used in the Quick start above.\n- [examples/config.sepolia.discovery.json](examples/config.sepolia.discovery.json)\n  — IERC7303 auto-discovery variant: no control tokens configured, the\n  target contract explains its own role structure.\n- [examples/contracts/](examples/contracts/) — sources of the demo\n  contracts deployed on Sepolia (`AgentControlTokens`,\n  `TCTCDemoToken`, `ERC7303`, `IERC7303`).\n\n## Demo deployment (Sepolia, Etherscan-verified)\n\n- `AgentControlTokens` (soulbound, issuer-burnable ERC-1155):\n  [`0x12342A7F0190B3AF3F4b47546D34006EDA54eE0B`](https://sepolia.etherscan.io/address/0x12342A7F0190B3AF3F4b47546D34006EDA54eE0B#code)\n- `TCTCDemoToken` (ERC-721 + ERC-7303 target, implements the\n  [`IERC7303` introspection interface](https://github.com/ethereum/ERCs/pull/1872)\n  — `hasRole`, control-token getters, ERC-165 detectable via interfaceId\n  `0x4ee69337`):\n  [`0x4C0a78803D47154B9C6F42EC4AEbab2D1C94c97D`](https://sepolia.etherscan.io/address/0x4C0a78803D47154B9C6F42EC4AEbab2D1C94c97D#code)\n- `ExpiringControlTokens` (soulbound, issuer-burnable ERC-1155 with\n  per-holder expiry; time-aware `balanceOf` — the basis of timed roles):\n  [`0xb5abB6c060ed287e8B25aD121c8B46eE404fF09b`](https://sepolia.etherscan.io/address/0xb5abB6c060ed287e8B25aD121c8B46eE404fF09b#code)\n- Expiry demo target (unmodified `TCTCDemoToken` bytecode bound to the\n  expiring control tokens):\n  [`0x3eAb11DE9655817A2e2977A486d9D33eBD10c9Ce`](https://sepolia.etherscan.io/address/0x3eAb11DE9655817A2e2977A486d9D33eBD10c9Ce#code)\n\n## Development\n\n```bash\ngit clone https://github.com/kofujimura/tctc-mcp.git && cd tctc-mcp\nnpm install && npm run build\nnode dist/index.js --config examples/config.sepolia.agent.json\n\nnpm test                  # unit tests (vitest)\nnode scripts/e2e-live.mjs # live E2E: spawns the server via MCP stdio client\n                          # (needs ALCHEMY_API_KEY; admin phase additionally\n                          #  TCTC_ADMIN_PRIVATE_KEY and E2E_SUBJECT)\n```\n\n## Related\n\n- Human dashboard (this repo, [`dashboard/`](dashboard/)):\n  <https://tctc-mcp.vercel.app/>\n- npm package: <https://www.npmjs.com/package/tctc-mcp>\n- [`tctc-gate`](gate/) — token-gate any existing MCP server, no\n  modification: <https://www.npmjs.com/package/tctc-gate>\n- [`tctc-openai-starter`](https://github.com/kofujimura/tctc-openai-starter)\n  — Next.js starter for token-gated OpenAI access.\n- Agent skill (teaches agents to use TCTC safely; install with\n  `npx skills add kofujimura/tctc-skills`):\n  <https://github.com/kofujimura/tctc-skills>\n- TCTC reference implementation: <https://github.com/kofujimura/TCTC>\n",
  "bytes": 12281,
  "sha": "6167ea1b59fed0a52641df6386d175895dbc2d694c98ac3b414b66ec88845f8b",
  "repo_slug": "kofujimura/tctc-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_kofujimura_tctc_mcp_39dd5199/readme"
}