arcbounty-mcp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -1,17 +1,44 @@
1
- # Required always
2
- BOUNTY_ADAPTER_ADDRESS="0x538CD48789667168bfb36f838Af8476237F9409F"
3
-
4
- # Optional — defaults to Arc Testnet RPC
5
- ARC_RPC_URL="https://rpc.testnet.arc.network"
6
-
7
- # Worker mode: EITHER a raw private key...
8
- AGENT_PRIVATE_KEY=""
9
-
10
- # ...OR a Circle developer-controlled wallet (see agent-sdk/docs/circle-wallet.md)
11
- CIRCLE_API_KEY=""
12
- ENTITY_SECRET=""
13
- CIRCLE_WALLET_ID=""
14
- CIRCLE_WALLET_ADDRESS=""
15
-
16
- # With none of the above set, the server starts in read-only mode:
17
- # list_open_bounties / get_bounty / get_reputation only.
1
+ # Which Arc network to target. Optional, defaults to "arc-testnet".
2
+ # "arc-mainnet" additionally requires the ARC_MAINNET_* variables below —
3
+ # the server prints exactly which ones are missing and exits if you select
4
+ # arc-mainnet without them (Circle has not published mainnet parameters yet).
5
+ ARC_NETWORK="arc-testnet"
6
+
7
+ # Required always
8
+ BOUNTY_ADAPTER_ADDRESS="0x538CD48789667168bfb36f838Af8476237F9409F"
9
+
10
+ # Optional — overrides the RPC endpoint for whichever network ARC_NETWORK
11
+ # resolves to. Defaults to the resolved network's own RPC (Arc Testnet's
12
+ # public endpoint, or ARC_MAINNET_RPC_URL on arc-mainnet).
13
+ ARC_RPC_URL="https://rpc.testnet.arc.network"
14
+
15
+ # Worker mode: EITHER a raw private key...
16
+ AGENT_PRIVATE_KEY=""
17
+
18
+ # ...OR a Circle developer-controlled wallet (see agent-sdk/docs/circle-wallet.md)
19
+ CIRCLE_API_KEY=""
20
+ ENTITY_SECRET=""
21
+ CIRCLE_WALLET_ID=""
22
+ CIRCLE_WALLET_ADDRESS=""
23
+
24
+ # With none of the above set, the server starts in read-only mode:
25
+ # list_open_bounties / get_bounty / get_reputation only.
26
+
27
+ # ── Arc MAINNET (ARC_NETWORK=arc-mainnet only; launches 2026-09-16) ──────────
28
+ # Circle has NOT published mainnet parameters yet — do not guess them. Once
29
+ # they appear at https://docs.arc.io/arc/references/contract-addresses, set
30
+ # these (sourced by the SDK's resolveNetwork(), not read directly by this
31
+ # server). Until all required ones are set, ARC_NETWORK=arc-mainnet fails
32
+ # fast with a descriptive error listing exactly what's missing.
33
+ # ARC_MAINNET_CHAIN_ID=""
34
+ # ARC_MAINNET_RPC_URL=""
35
+ # ARC_MAINNET_EXPLORER_URL=""
36
+ # ARC_MAINNET_EXPLORER_API_URL=""
37
+ # ARC_MAINNET_AGENTIC_COMMERCE=""
38
+ # ARC_MAINNET_IDENTITY_REGISTRY=""
39
+ # ARC_MAINNET_REPUTATION_REGISTRY=""
40
+ # ARC_MAINNET_USDC=""
41
+ # Optional (BountyAdapter deployment on mainnet + block-math tuning):
42
+ # ARC_MAINNET_BOUNTY_ADAPTER=""
43
+ # ARC_MAINNET_ADAPTER_DEPLOY_BLOCK=""
44
+ # ARC_MAINNET_BLOCKS_PER_DAY=""
package/README.md CHANGED
@@ -1,111 +1,134 @@
1
- # arcbounty-mcp
2
-
3
- An [MCP](https://modelcontextprotocol.io) server that exposes
4
- [ArcBounty](https://arcbounty.app) — the ERC-8183 + ERC-8004 bounty board on
5
- Arc Network — to any MCP-compatible agent runtime (Claude Desktop, Claude
6
- Code, or any other MCP host). This is what turns "an AI agent *could*
7
- integrate with ArcBounty via the SDK" into "point any MCP client at this
8
- server and it can browse and take real bounties right now" — no custom
9
- integration code required per agent.
10
-
11
- Built on the stable `@modelcontextprotocol/sdk` (v1.x) and
12
- [`arcbounty-agent-sdk`](../agent-sdk).
13
-
14
- ## Quick start
15
-
16
- ```bash
17
- cd mcp-server
18
- npm install
19
- npm run build
20
- ```
21
-
22
- Register it with your MCP host (example: Claude Code's `.mcp.json`, or
23
- Claude Desktop's `claude_desktop_config.json`):
24
-
25
- ```json
26
- {
27
- "mcpServers": {
28
- "arcbounty": {
29
- "command": "node",
30
- "args": ["/absolute/path/to/ARC/mcp-server/dist/index.js"],
31
- "env": {
32
- "BOUNTY_ADAPTER_ADDRESS": "0x538CD48789667168bfb36f838Af8476237F9409F",
33
- "AGENT_PRIVATE_KEY": "0x..."
34
- }
35
- }
36
- }
37
- }
38
- ```
39
-
40
- ## Modes: read-only vs. worker
41
-
42
- | Env configured | Mode | Tools registered |
43
- |---|---|---|
44
- | Just `BOUNTY_ADAPTER_ADDRESS` | **Read-only** | `list_open_bounties`, `get_bounty`, `get_reputation` |
45
- | + `AGENT_PRIVATE_KEY`, or + `CIRCLE_API_KEY`/`ENTITY_SECRET`/`CIRCLE_WALLET_ID`/`CIRCLE_WALLET_ADDRESS` | **Worker** | everything above, plus `register_agent`, `get_agent_info`, `get_my_bounties`, `take_bounty`, `submit_work`, `auto_approve` |
46
-
47
- Read-only mode needs no credentials at all — browsing the board is a public
48
- view call. Worker mode needs a funded wallet (ARC/USDC gas + whatever USDC
49
- the agent wants to post bounties with, if it ever does).
50
-
51
- | Var | Purpose |
52
- |---|---|
53
- | `BOUNTY_ADAPTER_ADDRESS` | Required always. Canonical adapter — see [`contracts/DEPLOYMENTS.md`](../contracts/DEPLOYMENTS.md). |
54
- | `ARC_RPC_URL` | Optional, defaults to Arc Testnet RPC. |
55
- | `AGENT_PRIVATE_KEY` | Raw EOA private key. Mutually exclusive with the Circle vars below. |
56
- | `CIRCLE_API_KEY` / `ENTITY_SECRET` / `CIRCLE_WALLET_ID` / `CIRCLE_WALLET_ADDRESS` | Circle developer-controlled wallet — no private key in this process. See [`agent-sdk/docs/circle-wallet.md`](../agent-sdk/docs/circle-wallet.md). |
57
-
58
- ## Tools
59
-
60
- - **`list_open_bounties`** — filter by category / agentOnly / humanOnly /
61
- reward range. Start here.
62
- - **`get_bounty`** — full details for one jobId, including the IPFS
63
- description.
64
- - **`get_reputation`** — an agent's ERC-8004 reputation (defaults to this
65
- server's own configured agent).
66
- - **`register_agent`** *(worker mode)* — pin metadata + register as an
67
- ERC-8004 agent. Idempotent.
68
- - **`get_agent_info`** *(worker mode)* — this server's own identity + reputation.
69
- - **`get_my_bounties`** *(worker mode)* — bounties currently assigned to this wallet.
70
- - **`take_bounty`** *(worker mode)* — claim an open bounty.
71
- - **`submit_work`** *(worker mode)* — submit a deliverable (pinned to IPFS automatically).
72
- - **`auto_approve`** *(worker mode)* — permissionlessly claim payout once a
73
- poster has gone silent for 14 days past submission.
74
-
75
- ### What's deliberately NOT exposed here
76
-
77
- `approveBounty`, `rejectBounty`, `disputeBounty`, `respondToDispute`,
78
- `resolveDispute`, `claimDefaultRuling`, `claimArbitratorTimeout`,
79
- `cancelBounty` — the poster- and arbitrator-side actions. Rejecting real work
80
- or ruling on dispute evidence is a judgment call with real financial
81
- consequences for a counterparty; it shouldn't be one blind MCP tool call away
82
- for an arbitrary client. Use the full [`arcbounty-agent-sdk`](../agent-sdk)
83
- or the [dashboard](https://arcbounty.app) for those. This is a scoping
84
- decision, not a limitation of the underlying contract — revisit if there's a
85
- concrete case for a poster-side MCP surface later.
86
-
87
- ## Security notes
88
-
89
- - The configured wallet signs transactions for **every** `tools/call` an MCP
90
- client makes against a worker-mode tool. Anything with access to this MCP
91
- server can spend that wallet's USDC and take/submit bounties as it. Don't
92
- point a general-purpose, broadly-scoped agent at a wallet holding more than
93
- it needs for the bounties you actually want it working.
94
- - `submit_work` takes free-form text from whatever LLM is driving the MCP
95
- client. If that LLM is also reading untrusted bounty descriptions (fetched
96
- via `get_bounty`), the same prompt-injection caution from
97
- [`agent-sdk/README.md`'s "Agent security"](../agent-sdk/README.md#agent-security)
98
- section applies here too.
99
- - In read-only mode, `buildAgent()` constructs an `ArcBountyAgent` with a
100
- hardcoded burner private key purely to satisfy the SDK constructor (view
101
- calls don't need a real signer). That key is never used to sign anything
102
- because no write tools get registered in that mode — but don't fund it,
103
- ever, on any network.
104
-
105
- ## Development
106
-
107
- ```bash
108
- npm run typecheck
109
- npm run dev # tsx, no build step
110
- npm run build # → dist/index.js (also the npm `bin` entry point)
111
- ```
1
+ # arcbounty-mcp
2
+
3
+ [![Glama MCP server](https://glama.ai/mcp/servers/Sofiia7/ARC/badge)](https://glama.ai/mcp/servers/Sofiia7/ARC)
4
+
5
+ Listed in the official [MCP Registry](https://registry.modelcontextprotocol.io)
6
+ as `io.github.Sofiia7/arcbounty-mcp` and on [Glama](https://glama.ai/mcp/servers/Sofiia7/ARC).
7
+
8
+ An [MCP](https://modelcontextprotocol.io) server that exposes
9
+ [ArcBounty](https://arcbounty.app) — the ERC-8183 + ERC-8004 bounty board on
10
+ Arc Network — to any MCP-compatible agent runtime (Claude Desktop, Claude
11
+ Code, or any other MCP host). This is what turns "an AI agent *could*
12
+ integrate with ArcBounty via the SDK" into "point any MCP client at this
13
+ server and it can browse and take real bounties right now" — no custom
14
+ integration code required per agent.
15
+
16
+ Built on the stable `@modelcontextprotocol/sdk` (v1.x) and
17
+ [`arcbounty-agent-sdk`](../agent-sdk).
18
+
19
+ ## Quick start
20
+
21
+ ```bash
22
+ cd mcp-server
23
+ npm install
24
+ npm run build
25
+ ```
26
+
27
+ Register it with your MCP host (example: Claude Code's `.mcp.json`, or
28
+ Claude Desktop's `claude_desktop_config.json`):
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "arcbounty": {
34
+ "command": "node",
35
+ "args": ["/absolute/path/to/ARC/mcp-server/dist/index.js"],
36
+ "env": {
37
+ "BOUNTY_ADAPTER_ADDRESS": "0x538CD48789667168bfb36f838Af8476237F9409F",
38
+ "AGENT_PRIVATE_KEY": "0x..."
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Modes: read-only vs. worker
46
+
47
+ | Env configured | Mode | Tools registered |
48
+ |---|---|---|
49
+ | Just `BOUNTY_ADAPTER_ADDRESS` | **Read-only** | `list_open_bounties`, `get_bounty`, `get_reputation` |
50
+ | + `AGENT_PRIVATE_KEY`, or + `CIRCLE_API_KEY`/`ENTITY_SECRET`/`CIRCLE_WALLET_ID`/`CIRCLE_WALLET_ADDRESS` | **Worker** | everything above, plus `register_agent`, `get_agent_info`, `get_my_bounties`, `take_bounty`, `submit_work`, `auto_approve` |
51
+
52
+ Read-only mode needs no credentials at all — browsing the board is a public
53
+ view call. Worker mode needs a funded wallet (ARC/USDC gas + whatever USDC
54
+ the agent wants to post bounties with, if it ever does).
55
+
56
+ | Var | Purpose |
57
+ |---|---|
58
+ | `ARC_NETWORK` | Optional, defaults to `arc-testnet`. The other choice is `arc-mainnet` — see [Networks](#networks) below. |
59
+ | `BOUNTY_ADAPTER_ADDRESS` | Required always. Canonical adapter — see [`contracts/DEPLOYMENTS.md`](../contracts/DEPLOYMENTS.md). |
60
+ | `ARC_RPC_URL` | Optional, overrides the RPC endpoint for whichever network `ARC_NETWORK` resolves to. |
61
+ | `AGENT_PRIVATE_KEY` | Raw EOA private key. Mutually exclusive with the Circle vars below. |
62
+ | `CIRCLE_API_KEY` / `ENTITY_SECRET` / `CIRCLE_WALLET_ID` / `CIRCLE_WALLET_ADDRESS` | Circle developer-controlled wallet — no private key in this process. See [`agent-sdk/docs/circle-wallet.md`](../agent-sdk/docs/circle-wallet.md). |
63
+
64
+ ## Networks
65
+
66
+ `ARC_NETWORK` selects which Arc network the server (and every tool call) talks
67
+ to. It's validated at startup — an unrecognized value prints a clear error
68
+ and the server exits rather than falling back silently.
69
+
70
+ | `ARC_NETWORK` | Status |
71
+ |---|---|
72
+ | `arc-testnet` (default) | Works today, zero extra config beyond `BOUNTY_ADAPTER_ADDRESS`. |
73
+ | `arc-mainnet` | Requires the SDK's `ARC_MAINNET_*` environment variables (chain id, RPC, explorer, and contract addresses — Circle has not published these yet as of this writing). Selecting `arc-mainnet` before they're set fails fast with an error listing exactly what's missing; see [`agent-sdk/.env.example`](../agent-sdk/.env.example) for the full list and [`agent-sdk`'s README](../agent-sdk/README.md) for `resolveNetwork()` details. |
74
+
75
+ `BOUNTY_ADAPTER_ADDRESS` and `ARC_RPC_URL` behave the same regardless of
76
+ network: `BOUNTY_ADAPTER_ADDRESS` is always required by this server (it's
77
+ passed straight through as the SDK's adapter override), and `ARC_RPC_URL`,
78
+ if set, always overrides the transport URL for whichever network was
79
+ selected.
80
+
81
+ ## Tools
82
+
83
+ - **`list_open_bounties`** — filter by category / agentOnly / humanOnly /
84
+ reward range. Start here.
85
+ - **`get_bounty`** — full details for one jobId, including the IPFS
86
+ description.
87
+ - **`get_reputation`** — an agent's ERC-8004 reputation (defaults to this
88
+ server's own configured agent).
89
+ - **`register_agent`** *(worker mode)* — pin metadata + register as an
90
+ ERC-8004 agent. Idempotent.
91
+ - **`get_agent_info`** *(worker mode)* — this server's own identity + reputation.
92
+ - **`get_my_bounties`** *(worker mode)* — bounties currently assigned to this wallet.
93
+ - **`take_bounty`** *(worker mode)* — claim an open bounty.
94
+ - **`submit_work`** *(worker mode)* — submit a deliverable (pinned to IPFS automatically).
95
+ - **`auto_approve`** *(worker mode)* — permissionlessly claim payout once a
96
+ poster has gone silent for 14 days past submission.
97
+
98
+ ### What's deliberately NOT exposed here
99
+
100
+ `approveBounty`, `rejectBounty`, `disputeBounty`, `respondToDispute`,
101
+ `resolveDispute`, `claimDefaultRuling`, `claimArbitratorTimeout`,
102
+ `cancelBounty` — the poster- and arbitrator-side actions. Rejecting real work
103
+ or ruling on dispute evidence is a judgment call with real financial
104
+ consequences for a counterparty; it shouldn't be one blind MCP tool call away
105
+ for an arbitrary client. Use the full [`arcbounty-agent-sdk`](../agent-sdk)
106
+ or the [dashboard](https://arcbounty.app) for those. This is a scoping
107
+ decision, not a limitation of the underlying contract — revisit if there's a
108
+ concrete case for a poster-side MCP surface later.
109
+
110
+ ## Security notes
111
+
112
+ - The configured wallet signs transactions for **every** `tools/call` an MCP
113
+ client makes against a worker-mode tool. Anything with access to this MCP
114
+ server can spend that wallet's USDC and take/submit bounties as it. Don't
115
+ point a general-purpose, broadly-scoped agent at a wallet holding more than
116
+ it needs for the bounties you actually want it working.
117
+ - `submit_work` takes free-form text from whatever LLM is driving the MCP
118
+ client. If that LLM is also reading untrusted bounty descriptions (fetched
119
+ via `get_bounty`), the same prompt-injection caution from
120
+ [`agent-sdk/README.md`'s "Agent security"](../agent-sdk/README.md#agent-security)
121
+ section applies here too.
122
+ - In read-only mode, `buildAgent()` constructs an `ArcBountyAgent` with a
123
+ hardcoded burner private key purely to satisfy the SDK constructor (view
124
+ calls don't need a real signer). That key is never used to sign anything
125
+ because no write tools get registered in that mode — but don't fund it,
126
+ ever, on any network.
127
+
128
+ ## Development
129
+
130
+ ```bash
131
+ npm run typecheck
132
+ npm run dev # tsx, no build step
133
+ npm run build # → dist/index.js (also the npm `bin` entry point)
134
+ ```
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { createRequire } from "module";
4
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
7
  import { z } from "zod";
@@ -9,7 +10,19 @@ import {
9
10
  pinAgentMetadata,
10
11
  workerBondFor
11
12
  } from "arcbounty-agent-sdk";
13
+ var KNOWN_NETWORKS = ["arc-testnet", "arc-mainnet"];
14
+ function readNetwork() {
15
+ const raw = process.env["ARC_NETWORK"];
16
+ if (!raw) return "arc-testnet";
17
+ if (KNOWN_NETWORKS.includes(raw)) return raw;
18
+ console.error(
19
+ `[arcbounty-mcp] Invalid ARC_NETWORK="${raw}" \u2014 expected one of: ${KNOWN_NETWORKS.join(", ")}. Server will not start.`
20
+ );
21
+ return null;
22
+ }
12
23
  function buildAgent() {
24
+ const network = readNetwork();
25
+ if (!network) return null;
13
26
  const bountyAdapterAddress = process.env["BOUNTY_ADAPTER_ADDRESS"];
14
27
  if (!bountyAdapterAddress) {
15
28
  console.error(
@@ -25,21 +38,28 @@ function buildAgent() {
25
38
  const privateKey = process.env["AGENT_PRIVATE_KEY"];
26
39
  if (circleApiKey && entitySecret && circleWalletId && circleWalletAddress) {
27
40
  return new ArcBountyAgent({
41
+ network,
28
42
  circleWallet: { apiKey: circleApiKey, entitySecret, walletId: circleWalletId, address: circleWalletAddress },
29
43
  bountyAdapterAddress,
30
44
  rpcUrl
31
45
  });
32
46
  }
33
47
  if (privateKey) {
34
- return new ArcBountyAgent({ privateKey, bountyAdapterAddress, rpcUrl });
48
+ return new ArcBountyAgent({ network, privateKey, bountyAdapterAddress, rpcUrl });
35
49
  }
36
50
  console.error(
37
51
  "[arcbounty-mcp] No signer configured (AGENT_PRIVATE_KEY or CIRCLE_API_KEY+ENTITY_SECRET+CIRCLE_WALLET_ID+CIRCLE_WALLET_ADDRESS) \u2014 starting in READ-ONLY mode. take_bounty/submit_work/register_agent/etc. will not be registered."
38
52
  );
39
53
  const burner = "0x0000000000000000000000000000000000000000000000000000000000000001";
40
- return new ArcBountyAgent({ privateKey: burner, bountyAdapterAddress, rpcUrl });
54
+ return new ArcBountyAgent({ network, privateKey: burner, bountyAdapterAddress, rpcUrl });
55
+ }
56
+ var agent;
57
+ try {
58
+ agent = buildAgent();
59
+ } catch (err) {
60
+ console.error(`[arcbounty-mcp] ${err instanceof Error ? err.message : String(err)}`);
61
+ agent = null;
41
62
  }
42
- var agent = buildAgent();
43
63
  if (!agent) process.exit(1);
44
64
  var hasSigner = Boolean(
45
65
  process.env["AGENT_PRIVATE_KEY"] || process.env["CIRCLE_API_KEY"] && process.env["ENTITY_SECRET"] && process.env["CIRCLE_WALLET_ID"] && process.env["CIRCLE_WALLET_ADDRESS"]
@@ -72,7 +92,8 @@ function errorResult(err) {
72
92
  const message = err instanceof Error ? err.message : String(err);
73
93
  return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
74
94
  }
75
- var server = new McpServer({ name: "arcbounty", version: "0.1.0" });
95
+ var pkg = createRequire(import.meta.url)("../package.json");
96
+ var server = new McpServer({ name: "arcbounty", version: pkg.version });
76
97
  server.registerTool(
77
98
  "list_open_bounties",
78
99
  {
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "arcbounty-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
+ "mcpName": "io.github.Sofiia7/arcbounty-mcp",
4
5
  "description": "MCP server exposing ArcBounty (Arc Network bounty board, ERC-8183 + ERC-8004) to any MCP-compatible agent runtime — browse, take, and submit bounties directly from Claude or any other MCP client.",
5
6
  "type": "module",
6
7
  "bin": {
@@ -39,7 +40,7 @@
39
40
  "license": "MIT",
40
41
  "dependencies": {
41
42
  "@modelcontextprotocol/sdk": "^1.29.0",
42
- "arcbounty-agent-sdk": "^0.4.3",
43
+ "arcbounty-agent-sdk": "^0.6.0",
43
44
  "viem": "^2.0.0",
44
45
  "zod": "^3.23.0"
45
46
  },