@arcisprotocol/mcp 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,10 +1,51 @@
1
- # @arcis/mcp
1
+ # @arcisprotocol/mcp
2
2
 
3
3
  Arcis Protocol MCP Server — connect any AI agent to DeFi vaults in one tool call.
4
4
 
5
- ## What This Does
5
+ Supports **two modes**: local (stdio) for Claude Desktop/Code, and remote (HTTP) for Claude.ai custom connectors.
6
6
 
7
- Any LLM that supports MCP (Claude, GPT, etc.) can interact with Arcis Protocol's on-chain contracts through natural language. No SDK, no code, no ABI decoding. The agent says "deposit 1000 USDC into Arcis" and the MCP tool handles everything.
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @arcisprotocol/mcp
11
+ ```
12
+
13
+ ## Mode 1: Local (Claude Desktop / Claude Code)
14
+
15
+ Add to `~/.claude/claude_desktop_config.json`:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "arcis": {
21
+ "command": "npx",
22
+ "args": ["@arcisprotocol/mcp"]
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## Mode 2: Remote (Claude.ai Custom Connector)
29
+
30
+ Start the HTTP server:
31
+
32
+ ```bash
33
+ npx @arcisprotocol/mcp start:remote
34
+ # or
35
+ PORT=3001 node -e "import('@arcisprotocol/mcp/dist/remote.js')"
36
+ ```
37
+
38
+ Then in Claude.ai: **Settings → Connectors → Add Custom Connector** → paste your server URL (e.g. `https://mcp.arcis.money/mcp`).
39
+
40
+ ### Deploy to production
41
+
42
+ ```bash
43
+ git clone https://github.com/Arcis-Protocol/mcp.git
44
+ cd mcp && npm install && npm run build
45
+ PORT=3001 node dist/remote.js
46
+ ```
47
+
48
+ Use a reverse proxy (nginx, Caddy) or deploy to Railway / Render / Fly.io for a persistent URL.
8
49
 
9
50
  ## Tools
10
51
 
@@ -14,18 +55,18 @@ Any LLM that supports MCP (Claude, GPT, etc.) can interact with Arcis Protocol's
14
55
  |---|---|
15
56
  | `arcis_vault_status` | TVL, exchange rate, supply, capacity, reserve/deployed |
16
57
  | `arcis_vault_balance` | Agent position: shares, value, USDC wallet |
17
- | `arcis_preview_deposit` | Preview shares received for a given deposit |
58
+ | `arcis_preview_deposit` | Preview shares for a deposit amount |
18
59
  | `arcis_credit_status` | Lending pool, total borrowed, utilization |
19
60
  | `arcis_credit_tiers` | ERC-8004 reputation tier table |
20
- | `arcis_credit_health` | Check if a loan is healthy |
61
+ | `arcis_credit_health` | Check loan health + total owed |
21
62
  | `arcis_contracts` | All 7 deployed contract addresses |
22
63
 
23
64
  ### Write (private key required)
24
65
 
25
66
  | Tool | Description |
26
67
  |---|---|
27
- | `arcis_deposit` | Deposit USDC → receive raUSDC (auto-approves) |
28
- | `arcis_withdraw` | Redeem raUSDC → receive USDC (supports withdraw_all) |
68
+ | `arcis_deposit` | Deposit USDC → raUSDC (auto-approval) |
69
+ | `arcis_withdraw` | Redeem raUSDC → USDC (supports withdraw_all) |
29
70
 
30
71
  ### Resources
31
72
 
@@ -33,56 +74,9 @@ Any LLM that supports MCP (Claude, GPT, etc.) can interact with Arcis Protocol's
33
74
  |---|---|
34
75
  | `arcis://protocol-info` | Protocol overview, ATI spec, product descriptions |
35
76
 
36
- ## Setup
37
-
38
- ```bash
39
- git clone https://github.com/Arcis-Protocol/mcp.git
40
- cd mcp && npm install
41
- npm run dev
42
- ```
43
-
44
- ## Connect to Claude
45
-
46
- Add to your Claude desktop config (`~/.claude/claude_desktop_config.json`):
47
-
48
- ```json
49
- {
50
- "mcpServers": {
51
- "arcis": {
52
- "command": "npx",
53
- "args": ["tsx", "/path/to/arcis-mcp/src/index.ts"]
54
- }
55
- }
56
- }
57
- ```
58
-
59
- ## Example Interactions
60
-
61
- > "What's the TVL on Arcis?"
62
- > → Calls `arcis_vault_status`, returns $11,250.00
63
-
64
- > "Check agent 0xB390...57db's position"
65
- > → Calls `arcis_vault_balance`, returns shares + value + wallet
66
-
67
- > "Deposit 500 USDC"
68
- > → Calls `arcis_deposit`, handles approval, returns tx hash + explorer link
69
-
70
- > "What are the credit tiers?"
71
- > → Calls `arcis_credit_tiers`, returns 5-tier table with collateral ratios
72
-
73
77
  ## Network
74
78
 
75
- Currently targets Base Sepolia testnet. Mainnet addresses will be updated after deployment.
76
-
77
- ## Related Repos
78
-
79
- | Repo | Description |
80
- |---|---|
81
- | [`core`](https://github.com/Arcis-Protocol/core) | Smart contracts (Foundry) |
82
- | [`sdk`](https://github.com/Arcis-Protocol/sdk) | TypeScript SDK |
83
- | [`cli`](https://github.com/Arcis-Protocol/cli) | Terminal interface (TUI) |
84
- | [`app`](https://github.com/Arcis-Protocol/app) | arcis.money |
85
- | [`docs`](https://github.com/Arcis-Protocol/docs) | Protocol documentation |
79
+ Currently targets Base Sepolia testnet. Mainnet addresses updated after deployment.
86
80
 
87
81
  ---
88
82
 
@@ -0,0 +1,404 @@
1
+ // src/server.ts
2
+ import { MCPServer, object, error, markdown } from "mcp-use/server";
3
+ import { z } from "zod";
4
+ import { createPublicClient, createWalletClient, http, defineChain, formatUnits } from "viem";
5
+ import { privateKeyToAccount } from "viem/accounts";
6
+ var baseSepolia = defineChain({
7
+ id: 84532,
8
+ name: "Base Sepolia",
9
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
10
+ rpcUrls: { default: { http: ["https://sepolia.base.org"] } },
11
+ blockExplorers: { default: { name: "Blockscout", url: "https://base-sepolia.blockscout.com" } }
12
+ });
13
+ var ADDR = {
14
+ vault: "0xa8eF658E125C7f6D7aFa9B6b8035b66b32CBE98d",
15
+ credit: "0x019540E33a0292a9DDE36bD9Ef11774d5A1Ce6FC",
16
+ router: "0x0281e7D37683c585325004F84e0b94170c78d5B4",
17
+ usdc: "0x29440A12f15fe6bDf5F624f4eeEB298CCb782f05",
18
+ allocator: "0x9f101e1159AA530dC5Cb104decB32aBA1eAF2617",
19
+ strategy: "0x9d6FB397224141FD323096e95667d3Ae5D9FF9cC",
20
+ identity: "0x79E79629DB86CFb8feF9594621882b065EBC80A7"
21
+ };
22
+ var VAULT_ABI = [
23
+ { name: "deposit", type: "function", inputs: [{ name: "amount", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "nonpayable" },
24
+ { name: "withdraw", type: "function", inputs: [{ name: "shares", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "nonpayable" },
25
+ { name: "balance", type: "function", inputs: [{ name: "agent", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
26
+ { name: "balanceOf", type: "function", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
27
+ { name: "totalAssets", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
28
+ { name: "totalSupply", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
29
+ { name: "exchangeRate", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
30
+ { name: "depositCap", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
31
+ { name: "remainingCapacity", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
32
+ { name: "reserveBalance", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
33
+ { name: "deployedBalance", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
34
+ { name: "paused", type: "function", inputs: [], outputs: [{ name: "", type: "bool" }], stateMutability: "view" },
35
+ { name: "previewDeposit", type: "function", inputs: [{ name: "assets", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
36
+ { name: "previewWithdraw", type: "function", inputs: [{ name: "shares", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" }
37
+ ];
38
+ var CREDIT_ABI = [
39
+ { name: "lendingPool", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
40
+ { name: "totalBorrowed", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
41
+ { name: "collateralRatios", type: "function", inputs: [{ name: "tier", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
42
+ { name: "totalOwed", type: "function", inputs: [{ name: "loanId", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
43
+ { name: "isHealthy", type: "function", inputs: [{ name: "loanId", type: "uint256" }], outputs: [{ name: "", type: "bool" }], stateMutability: "view" }
44
+ ];
45
+ var ERC20_ABI = [
46
+ { name: "approve", type: "function", inputs: [{ name: "spender", type: "address" }, { name: "amount", type: "uint256" }], outputs: [{ name: "", type: "bool" }], stateMutability: "nonpayable" },
47
+ { name: "balanceOf", type: "function", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
48
+ { name: "allowance", type: "function", inputs: [{ name: "owner", type: "address" }, { name: "spender", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" }
49
+ ];
50
+ var client = createPublicClient({ chain: baseSepolia, transport: http() });
51
+ var fmtUSDC = (raw) => formatUnits(raw, 6);
52
+ var fmtRate = (raw) => {
53
+ const n = Number(raw) / 1e18;
54
+ return n > 1e3 || n < 1e-4 ? "1.000000" : n.toFixed(6);
55
+ };
56
+ var writeRateLimit = /* @__PURE__ */ new Map();
57
+ var WRITE_COOLDOWN_MS = 6e4;
58
+ function checkRateLimit(key) {
59
+ const last = writeRateLimit.get(key) || 0;
60
+ const remaining = WRITE_COOLDOWN_MS - (Date.now() - last);
61
+ if (remaining > 0) return `Rate limited. Try again in ${Math.ceil(remaining / 1e3)}s.`;
62
+ writeRateLimit.set(key, Date.now());
63
+ return null;
64
+ }
65
+ var server = new MCPServer({
66
+ name: "arcis-protocol",
67
+ title: "Arcis Protocol",
68
+ description: "Financial infrastructure for autonomous AI agents \u2014 yield vaults, credit, and bonds on Base",
69
+ version: "0.1.0"
70
+ });
71
+ server.tool(
72
+ {
73
+ name: "arcis_vault_status",
74
+ description: "Get the current vault status: TVL, exchange rate, raUSDC supply, deposit cap, reserve/deployed split, and pause state. No parameters needed.",
75
+ schema: z.object({})
76
+ },
77
+ async () => {
78
+ try {
79
+ const [totalAssets, totalSupply, rate, cap, remaining, reserve, deployed, paused] = await Promise.all([
80
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "totalAssets" }),
81
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "totalSupply" }),
82
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "exchangeRate" }),
83
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "depositCap" }),
84
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "remainingCapacity" }),
85
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "reserveBalance" }),
86
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "deployedBalance" }),
87
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "paused" })
88
+ ]);
89
+ const utilPct = cap > 0n ? (Number(totalAssets * 10000n / cap) / 100).toFixed(2) : "0";
90
+ const resPct = totalAssets > 0n ? (Number(reserve * 10000n / totalAssets) / 100).toFixed(1) : "0";
91
+ return object({
92
+ network: "Base Sepolia (84532)",
93
+ contract: ADDR.vault,
94
+ status: paused ? "PAUSED" : "ACTIVE",
95
+ tvl_usdc: fmtUSDC(totalAssets),
96
+ rausdc_supply: fmtUSDC(totalSupply),
97
+ exchange_rate: totalSupply > 0n ? fmtRate(rate) : "1.000000",
98
+ reserve_usdc: fmtUSDC(reserve),
99
+ reserve_pct: resPct + "%",
100
+ deployed_usdc: fmtUSDC(deployed),
101
+ deposit_cap_usdc: cap > 0n ? fmtUSDC(cap) : "No cap set",
102
+ remaining_capacity: cap > 0n ? fmtUSDC(remaining) : "Unlimited",
103
+ utilization: utilPct + "%",
104
+ explorer: `https://base-sepolia.blockscout.com/address/${ADDR.vault}`
105
+ });
106
+ } catch (e) {
107
+ return error("Failed to fetch vault status: " + e.message);
108
+ }
109
+ }
110
+ );
111
+ server.tool(
112
+ {
113
+ name: "arcis_vault_balance",
114
+ description: "Check an agent's vault position: raUSDC shares held, position value in USDC, and USDC wallet balance.",
115
+ schema: z.object({
116
+ address: z.string().describe("The agent's Ethereum address (0x...)")
117
+ })
118
+ },
119
+ async ({ address }) => {
120
+ try {
121
+ const agent = address;
122
+ const [shares, value, usdcBal] = await Promise.all([
123
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balanceOf", args: [agent] }),
124
+ client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balance", args: [agent] }),
125
+ client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "balanceOf", args: [agent] })
126
+ ]);
127
+ return object({
128
+ agent: address,
129
+ rausdc_shares: fmtUSDC(shares),
130
+ position_value_usdc: fmtUSDC(value),
131
+ usdc_wallet_balance: fmtUSDC(usdcBal)
132
+ });
133
+ } catch (e) {
134
+ return error("Failed to fetch balance: " + e.message);
135
+ }
136
+ }
137
+ );
138
+ server.tool(
139
+ {
140
+ name: "arcis_preview_deposit",
141
+ description: "Preview how many raUSDC shares a given USDC deposit would yield, without executing the transaction.",
142
+ schema: z.object({
143
+ amount: z.number().positive().describe("Amount of USDC to deposit (e.g. 1000 for $1,000)")
144
+ })
145
+ },
146
+ async ({ amount }) => {
147
+ try {
148
+ const raw = BigInt(Math.floor(amount * 1e6));
149
+ const shares = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewDeposit", args: [raw] });
150
+ return object({
151
+ deposit_usdc: amount.toString(),
152
+ shares_received: fmtUSDC(shares),
153
+ exchange_rate: (amount * 1e6 / Number(shares)).toFixed(6)
154
+ });
155
+ } catch (e) {
156
+ return error("Preview failed: " + e.message);
157
+ }
158
+ }
159
+ );
160
+ server.tool(
161
+ {
162
+ name: "arcis_credit_status",
163
+ description: "Get the credit module status: lending pool size, total borrowed, and utilization rate.",
164
+ schema: z.object({})
165
+ },
166
+ async () => {
167
+ try {
168
+ const [pool, borrowed] = await Promise.all([
169
+ client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "lendingPool" }),
170
+ client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "totalBorrowed" })
171
+ ]);
172
+ const total = pool + borrowed;
173
+ const utilPct = total > 0n ? (Number(borrowed * 10000n / total) / 100).toFixed(1) : "0";
174
+ return object({
175
+ contract: ADDR.credit,
176
+ lending_pool_usdc: fmtUSDC(pool),
177
+ total_borrowed_usdc: fmtUSDC(borrowed),
178
+ utilization: utilPct + "%"
179
+ });
180
+ } catch (e) {
181
+ return error("Failed to fetch credit status: " + e.message);
182
+ }
183
+ }
184
+ );
185
+ server.tool(
186
+ {
187
+ name: "arcis_credit_tiers",
188
+ description: "List all 5 ERC-8004 reputation tiers with their collateral ratios and rate discounts.",
189
+ schema: z.object({})
190
+ },
191
+ async () => {
192
+ try {
193
+ const labels = ["No Identity", "Novice (1-25)", "Active (26-50)", "Established (51-75)", "Elite (76-100)"];
194
+ const discounts = [0, 100, 200, 350, 500];
195
+ const ratios = await Promise.all(
196
+ [0, 1, 2, 3, 4].map(
197
+ (i) => client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "collateralRatios", args: [BigInt(i)] })
198
+ )
199
+ );
200
+ return object({
201
+ tiers: ratios.map((r, i) => ({
202
+ tier: i,
203
+ label: labels[i],
204
+ collateral_ratio: (Number(r) / 100).toFixed(1) + "%",
205
+ rate_discount_bps: discounts[i]
206
+ }))
207
+ });
208
+ } catch (e) {
209
+ return error("Failed to fetch tiers: " + e.message);
210
+ }
211
+ }
212
+ );
213
+ server.tool(
214
+ {
215
+ name: "arcis_credit_health",
216
+ description: "Check whether a specific loan is healthy (sufficiently collateralized) and how much is owed.",
217
+ schema: z.object({
218
+ loan_id: z.number().int().positive().describe("The loan ID to check")
219
+ })
220
+ },
221
+ async ({ loan_id }) => {
222
+ try {
223
+ const [healthy, owed] = await Promise.all([
224
+ client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "isHealthy", args: [BigInt(loan_id)] }),
225
+ client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "totalOwed", args: [BigInt(loan_id)] })
226
+ ]);
227
+ return object({
228
+ loan_id,
229
+ healthy,
230
+ total_owed_usdc: fmtUSDC(owed),
231
+ status: healthy ? "HEALTHY" : "UNDERCOLLATERALIZED"
232
+ });
233
+ } catch (e) {
234
+ return error("Failed to check loan health: " + e.message);
235
+ }
236
+ }
237
+ );
238
+ server.tool(
239
+ {
240
+ name: "arcis_contracts",
241
+ description: "List all deployed Arcis Protocol contract addresses on Base Sepolia with their roles.",
242
+ schema: z.object({})
243
+ },
244
+ async () => {
245
+ return object({
246
+ network: "Base Sepolia (84532)",
247
+ explorer: "https://base-sepolia.blockscout.com",
248
+ contracts: {
249
+ ArcisVault: { address: ADDR.vault, role: "ERC-4626 yield vault (raUSDC)" },
250
+ AgentCredit: { address: ADDR.credit, role: "ERC-8004 identity-aware lending" },
251
+ ATIRouter: { address: ADDR.router, role: "Multi-vault entry point" },
252
+ StrategyAllocator: { address: ADDR.allocator, role: "Yield strategy weights" },
253
+ MockStrategy: { address: ADDR.strategy, role: "Testnet yield strategy" },
254
+ MockUSDC: { address: ADDR.usdc, role: "Testnet USDC" },
255
+ MockIdentityRegistry: { address: ADDR.identity, role: "ERC-8004 test registry" }
256
+ },
257
+ ati_standard: {
258
+ deposit: "deposit(uint256 amount) \u2192 uint256 shares",
259
+ withdraw: "withdraw(uint256 shares) \u2192 uint256 amount",
260
+ balance: "balance(address agent) \u2192 uint256 value"
261
+ }
262
+ });
263
+ }
264
+ );
265
+ server.tool(
266
+ {
267
+ name: "arcis_deposit",
268
+ description: "Deposit USDC into the Arcis vault and receive raUSDC shares. Handles USDC approval automatically. Requires an agent private key.",
269
+ schema: z.object({
270
+ amount: z.number().positive().describe("Amount of USDC to deposit (e.g. 1000 for $1,000)"),
271
+ private_key: z.string().describe("Agent's private key (0x...) for signing the transaction")
272
+ })
273
+ },
274
+ async ({ amount, private_key }) => {
275
+ try {
276
+ const rateErr = checkRateLimit(private_key.slice(0, 10));
277
+ if (rateErr) return error(rateErr);
278
+ const amountRaw = BigInt(Math.floor(amount * 1e6));
279
+ const account = privateKeyToAccount(private_key);
280
+ const wallet = createWalletClient({ chain: baseSepolia, transport: http(), account });
281
+ const usdcBal = await client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "balanceOf", args: [account.address] });
282
+ if (usdcBal < amountRaw) {
283
+ return error(`Insufficient USDC. Have ${fmtUSDC(usdcBal)}, need ${fmtUSDC(amountRaw)}`);
284
+ }
285
+ const allowance = await client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "allowance", args: [account.address, ADDR.vault] });
286
+ if (allowance < amountRaw) {
287
+ const approveTx = await wallet.writeContract({
288
+ address: ADDR.usdc,
289
+ abi: ERC20_ABI,
290
+ functionName: "approve",
291
+ args: [ADDR.vault, 2n ** 256n - 1n],
292
+ chain: baseSepolia,
293
+ account
294
+ });
295
+ await client.waitForTransactionReceipt({ hash: approveTx });
296
+ }
297
+ const sharesPreview = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewDeposit", args: [amountRaw] });
298
+ const tx = await wallet.writeContract({
299
+ address: ADDR.vault,
300
+ abi: VAULT_ABI,
301
+ functionName: "deposit",
302
+ args: [amountRaw],
303
+ chain: baseSepolia,
304
+ account
305
+ });
306
+ const receipt = await client.waitForTransactionReceipt({ hash: tx });
307
+ return object({
308
+ status: "SUCCESS",
309
+ deposited_usdc: amount.toString(),
310
+ shares_received: fmtUSDC(sharesPreview),
311
+ tx_hash: tx,
312
+ block: Number(receipt.blockNumber),
313
+ gas_used: Number(receipt.gasUsed),
314
+ explorer: `https://base-sepolia.blockscout.com/tx/${tx}`
315
+ });
316
+ } catch (e) {
317
+ return error("Deposit failed: " + e.message);
318
+ }
319
+ }
320
+ );
321
+ server.tool(
322
+ {
323
+ name: "arcis_withdraw",
324
+ description: "Withdraw USDC from the Arcis vault by redeeming raUSDC shares. Use withdraw_all to redeem entire position.",
325
+ schema: z.object({
326
+ shares: z.number().positive().optional().describe("Amount of raUSDC shares to redeem (omit to withdraw all)"),
327
+ private_key: z.string().describe("Agent's private key (0x...) for signing the transaction"),
328
+ withdraw_all: z.boolean().optional().describe("Set to true to withdraw entire position")
329
+ })
330
+ },
331
+ async ({ shares, private_key, withdraw_all }) => {
332
+ try {
333
+ const rateErr = checkRateLimit(private_key.slice(0, 10));
334
+ if (rateErr) return error(rateErr);
335
+ const account = privateKeyToAccount(private_key);
336
+ const wallet = createWalletClient({ chain: baseSepolia, transport: http(), account });
337
+ let sharesRaw;
338
+ if (withdraw_all) {
339
+ sharesRaw = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balanceOf", args: [account.address] });
340
+ if (sharesRaw === 0n) return error("No shares to withdraw");
341
+ } else if (shares) {
342
+ sharesRaw = BigInt(Math.floor(shares * 1e6));
343
+ } else {
344
+ return error("Provide either shares amount or set withdraw_all to true");
345
+ }
346
+ const usdcPreview = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewWithdraw", args: [sharesRaw] });
347
+ const tx = await wallet.writeContract({
348
+ address: ADDR.vault,
349
+ abi: VAULT_ABI,
350
+ functionName: "withdraw",
351
+ args: [sharesRaw],
352
+ chain: baseSepolia,
353
+ account
354
+ });
355
+ const receipt = await client.waitForTransactionReceipt({ hash: tx });
356
+ return object({
357
+ status: "SUCCESS",
358
+ shares_redeemed: fmtUSDC(sharesRaw),
359
+ usdc_received: fmtUSDC(usdcPreview),
360
+ tx_hash: tx,
361
+ block: Number(receipt.blockNumber),
362
+ explorer: `https://base-sepolia.blockscout.com/tx/${tx}`
363
+ });
364
+ } catch (e) {
365
+ return error("Withdraw failed: " + e.message);
366
+ }
367
+ }
368
+ );
369
+ server.resource(
370
+ {
371
+ uri: "arcis://protocol-info",
372
+ name: "Arcis Protocol Info",
373
+ description: "Overview of Arcis Protocol \u2014 what it is, how it works, and how agents interact with it",
374
+ mimeType: "text/markdown"
375
+ },
376
+ async () => markdown(`# Arcis Protocol
377
+
378
+ **The citadel of agent capital.**
379
+
380
+ Arcis builds financial infrastructure for autonomous AI agents: yield-bearing vaults, identity-aware credit lines, and revenue bonds. Deployed on Base.
381
+
382
+ ## ATI Standard (Agent Treasury Interface)
383
+
384
+ Three functions. Any agent framework.
385
+
386
+ - \`deposit(uint256 amount) \u2192 uint256 shares\` \u2014 Deposit USDC, receive yield-bearing raUSDC
387
+ - \`withdraw(uint256 shares) \u2192 uint256 amount\` \u2014 Redeem raUSDC for USDC + accrued yield
388
+ - \`balance(address agent) \u2192 uint256 value\` \u2014 Check position value in USDC
389
+
390
+ ## Products
391
+
392
+ 1. **Agent Vaults** \u2014 ERC-4626 vaults where agents park idle USDC. Yield via Aave/Morpho strategies. Management fee: 2% on yield.
393
+ 2. **Agent Credit** \u2014 ERC-8004 reputation-aware lending. 5 tiers from 200% to 115% collateral based on on-chain identity score.
394
+ 3. **Revenue Bonds** \u2014 Agents with consistent revenue issue tokenized bonds. Human investors buy fixed yield.
395
+
396
+ ## Links
397
+
398
+ - Website: https://arcis.money
399
+ - Dashboard: https://arcis.money/dashboard
400
+ - GitHub: https://github.com/Arcis-Protocol
401
+ - Telegram: https://t.me/arcisprotocol
402
+ - X: https://x.com/ArcisProtocol
403
+ `)
404
+ );
package/dist/index.js CHANGED
@@ -1,394 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-6OFSQEDB.js";
2
3
 
3
4
  // src/index.ts
4
- import { MCPServer, object, error, markdown } from "mcp-use/server";
5
- import { z } from "zod";
6
- import { createPublicClient, createWalletClient, http, defineChain, formatUnits } from "viem";
7
- import { privateKeyToAccount } from "viem/accounts";
8
- var baseSepolia = defineChain({
9
- id: 84532,
10
- name: "Base Sepolia",
11
- nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
12
- rpcUrls: { default: { http: ["https://sepolia.base.org"] } },
13
- blockExplorers: { default: { name: "Blockscout", url: "https://base-sepolia.blockscout.com" } }
14
- });
15
- var ADDR = {
16
- vault: "0xa8eF658E125C7f6D7aFa9B6b8035b66b32CBE98d",
17
- credit: "0x019540E33a0292a9DDE36bD9Ef11774d5A1Ce6FC",
18
- router: "0x0281e7D37683c585325004F84e0b94170c78d5B4",
19
- usdc: "0x29440A12f15fe6bDf5F624f4eeEB298CCb782f05",
20
- allocator: "0x9f101e1159AA530dC5Cb104decB32aBA1eAF2617",
21
- strategy: "0x9d6FB397224141FD323096e95667d3Ae5D9FF9cC",
22
- identity: "0x79E79629DB86CFb8feF9594621882b065EBC80A7"
23
- };
24
- var VAULT_ABI = [
25
- { name: "deposit", type: "function", inputs: [{ name: "amount", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "nonpayable" },
26
- { name: "withdraw", type: "function", inputs: [{ name: "shares", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "nonpayable" },
27
- { name: "balance", type: "function", inputs: [{ name: "agent", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
28
- { name: "balanceOf", type: "function", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
29
- { name: "totalAssets", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
30
- { name: "totalSupply", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
31
- { name: "exchangeRate", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
32
- { name: "depositCap", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
33
- { name: "remainingCapacity", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
34
- { name: "reserveBalance", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
35
- { name: "deployedBalance", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
36
- { name: "paused", type: "function", inputs: [], outputs: [{ name: "", type: "bool" }], stateMutability: "view" },
37
- { name: "previewDeposit", type: "function", inputs: [{ name: "assets", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
38
- { name: "previewWithdraw", type: "function", inputs: [{ name: "shares", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" }
39
- ];
40
- var CREDIT_ABI = [
41
- { name: "lendingPool", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
42
- { name: "totalBorrowed", type: "function", inputs: [], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
43
- { name: "collateralRatios", type: "function", inputs: [{ name: "tier", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
44
- { name: "totalOwed", type: "function", inputs: [{ name: "loanId", type: "uint256" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
45
- { name: "isHealthy", type: "function", inputs: [{ name: "loanId", type: "uint256" }], outputs: [{ name: "", type: "bool" }], stateMutability: "view" }
46
- ];
47
- var ERC20_ABI = [
48
- { name: "approve", type: "function", inputs: [{ name: "spender", type: "address" }, { name: "amount", type: "uint256" }], outputs: [{ name: "", type: "bool" }], stateMutability: "nonpayable" },
49
- { name: "balanceOf", type: "function", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" },
50
- { name: "allowance", type: "function", inputs: [{ name: "owner", type: "address" }, { name: "spender", type: "address" }], outputs: [{ name: "", type: "uint256" }], stateMutability: "view" }
51
- ];
52
- var client = createPublicClient({ chain: baseSepolia, transport: http() });
53
- var fmtUSDC = (raw) => formatUnits(raw, 6);
54
- var fmtRate = (raw) => {
55
- const n = Number(raw) / 1e18;
56
- return n > 1e3 || n < 1e-4 ? "1.000000" : n.toFixed(6);
57
- };
58
- var server = new MCPServer({
59
- name: "arcis-protocol",
60
- title: "Arcis Protocol",
61
- description: "Financial infrastructure for autonomous AI agents \u2014 yield vaults, credit, and bonds on Base",
62
- version: "0.1.0"
63
- });
64
- server.tool(
65
- {
66
- name: "arcis_vault_status",
67
- description: "Get the current vault status: TVL, exchange rate, raUSDC supply, deposit cap, reserve/deployed split, and pause state. No parameters needed.",
68
- schema: z.object({})
69
- },
70
- async () => {
71
- try {
72
- const [totalAssets, totalSupply, rate, cap, remaining, reserve, deployed, paused] = await Promise.all([
73
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "totalAssets" }),
74
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "totalSupply" }),
75
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "exchangeRate" }),
76
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "depositCap" }),
77
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "remainingCapacity" }),
78
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "reserveBalance" }),
79
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "deployedBalance" }),
80
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "paused" })
81
- ]);
82
- const utilPct = cap > 0n ? (Number(totalAssets * 10000n / cap) / 100).toFixed(2) : "0";
83
- const resPct = totalAssets > 0n ? (Number(reserve * 10000n / totalAssets) / 100).toFixed(1) : "0";
84
- return object({
85
- network: "Base Sepolia (84532)",
86
- contract: ADDR.vault,
87
- status: paused ? "PAUSED" : "ACTIVE",
88
- tvl_usdc: fmtUSDC(totalAssets),
89
- rausdc_supply: fmtUSDC(totalSupply),
90
- exchange_rate: totalSupply > 0n ? fmtRate(rate) : "1.000000",
91
- reserve_usdc: fmtUSDC(reserve),
92
- reserve_pct: resPct + "%",
93
- deployed_usdc: fmtUSDC(deployed),
94
- deposit_cap_usdc: cap > 0n ? fmtUSDC(cap) : "No cap set",
95
- remaining_capacity: cap > 0n ? fmtUSDC(remaining) : "Unlimited",
96
- utilization: utilPct + "%",
97
- explorer: `https://base-sepolia.blockscout.com/address/${ADDR.vault}`
98
- });
99
- } catch (e) {
100
- return error("Failed to fetch vault status: " + e.message);
101
- }
102
- }
103
- );
104
- server.tool(
105
- {
106
- name: "arcis_vault_balance",
107
- description: "Check an agent's vault position: raUSDC shares held, position value in USDC, and USDC wallet balance.",
108
- schema: z.object({
109
- address: z.string().describe("The agent's Ethereum address (0x...)")
110
- })
111
- },
112
- async ({ address }) => {
113
- try {
114
- const agent = address;
115
- const [shares, value, usdcBal] = await Promise.all([
116
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balanceOf", args: [agent] }),
117
- client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balance", args: [agent] }),
118
- client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "balanceOf", args: [agent] })
119
- ]);
120
- return object({
121
- agent: address,
122
- rausdc_shares: fmtUSDC(shares),
123
- position_value_usdc: fmtUSDC(value),
124
- usdc_wallet_balance: fmtUSDC(usdcBal)
125
- });
126
- } catch (e) {
127
- return error("Failed to fetch balance: " + e.message);
128
- }
129
- }
130
- );
131
- server.tool(
132
- {
133
- name: "arcis_preview_deposit",
134
- description: "Preview how many raUSDC shares a given USDC deposit would yield, without executing the transaction.",
135
- schema: z.object({
136
- amount: z.number().positive().describe("Amount of USDC to deposit (e.g. 1000 for $1,000)")
137
- })
138
- },
139
- async ({ amount }) => {
140
- try {
141
- const raw = BigInt(Math.floor(amount * 1e6));
142
- const shares = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewDeposit", args: [raw] });
143
- return object({
144
- deposit_usdc: amount.toString(),
145
- shares_received: fmtUSDC(shares),
146
- exchange_rate: (amount * 1e6 / Number(shares)).toFixed(6)
147
- });
148
- } catch (e) {
149
- return error("Preview failed: " + e.message);
150
- }
151
- }
152
- );
153
- server.tool(
154
- {
155
- name: "arcis_credit_status",
156
- description: "Get the credit module status: lending pool size, total borrowed, and utilization rate.",
157
- schema: z.object({})
158
- },
159
- async () => {
160
- try {
161
- const [pool, borrowed] = await Promise.all([
162
- client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "lendingPool" }),
163
- client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "totalBorrowed" })
164
- ]);
165
- const total = pool + borrowed;
166
- const utilPct = total > 0n ? (Number(borrowed * 10000n / total) / 100).toFixed(1) : "0";
167
- return object({
168
- contract: ADDR.credit,
169
- lending_pool_usdc: fmtUSDC(pool),
170
- total_borrowed_usdc: fmtUSDC(borrowed),
171
- utilization: utilPct + "%"
172
- });
173
- } catch (e) {
174
- return error("Failed to fetch credit status: " + e.message);
175
- }
176
- }
177
- );
178
- server.tool(
179
- {
180
- name: "arcis_credit_tiers",
181
- description: "List all 5 ERC-8004 reputation tiers with their collateral ratios and rate discounts.",
182
- schema: z.object({})
183
- },
184
- async () => {
185
- try {
186
- const labels = ["No Identity", "Novice (1-25)", "Active (26-50)", "Established (51-75)", "Elite (76-100)"];
187
- const discounts = [0, 100, 200, 350, 500];
188
- const ratios = await Promise.all(
189
- [0, 1, 2, 3, 4].map(
190
- (i) => client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "collateralRatios", args: [BigInt(i)] })
191
- )
192
- );
193
- return object({
194
- tiers: ratios.map((r, i) => ({
195
- tier: i,
196
- label: labels[i],
197
- collateral_ratio: (Number(r) / 100).toFixed(1) + "%",
198
- rate_discount_bps: discounts[i]
199
- }))
200
- });
201
- } catch (e) {
202
- return error("Failed to fetch tiers: " + e.message);
203
- }
204
- }
205
- );
206
- server.tool(
207
- {
208
- name: "arcis_credit_health",
209
- description: "Check whether a specific loan is healthy (sufficiently collateralized) and how much is owed.",
210
- schema: z.object({
211
- loan_id: z.number().int().positive().describe("The loan ID to check")
212
- })
213
- },
214
- async ({ loan_id }) => {
215
- try {
216
- const [healthy, owed] = await Promise.all([
217
- client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "isHealthy", args: [BigInt(loan_id)] }),
218
- client.readContract({ address: ADDR.credit, abi: CREDIT_ABI, functionName: "totalOwed", args: [BigInt(loan_id)] })
219
- ]);
220
- return object({
221
- loan_id,
222
- healthy,
223
- total_owed_usdc: fmtUSDC(owed),
224
- status: healthy ? "HEALTHY" : "UNDERCOLLATERALIZED"
225
- });
226
- } catch (e) {
227
- return error("Failed to check loan health: " + e.message);
228
- }
229
- }
230
- );
231
- server.tool(
232
- {
233
- name: "arcis_contracts",
234
- description: "List all deployed Arcis Protocol contract addresses on Base Sepolia with their roles.",
235
- schema: z.object({})
236
- },
237
- async () => {
238
- return object({
239
- network: "Base Sepolia (84532)",
240
- explorer: "https://base-sepolia.blockscout.com",
241
- contracts: {
242
- ArcisVault: { address: ADDR.vault, role: "ERC-4626 yield vault (raUSDC)" },
243
- AgentCredit: { address: ADDR.credit, role: "ERC-8004 identity-aware lending" },
244
- ATIRouter: { address: ADDR.router, role: "Multi-vault entry point" },
245
- StrategyAllocator: { address: ADDR.allocator, role: "Yield strategy weights" },
246
- MockStrategy: { address: ADDR.strategy, role: "Testnet yield strategy" },
247
- MockUSDC: { address: ADDR.usdc, role: "Testnet USDC" },
248
- MockIdentityRegistry: { address: ADDR.identity, role: "ERC-8004 test registry" }
249
- },
250
- ati_standard: {
251
- deposit: "deposit(uint256 amount) \u2192 uint256 shares",
252
- withdraw: "withdraw(uint256 shares) \u2192 uint256 amount",
253
- balance: "balance(address agent) \u2192 uint256 value"
254
- }
255
- });
256
- }
257
- );
258
- server.tool(
259
- {
260
- name: "arcis_deposit",
261
- description: "Deposit USDC into the Arcis vault and receive raUSDC shares. Handles USDC approval automatically. Requires an agent private key.",
262
- schema: z.object({
263
- amount: z.number().positive().describe("Amount of USDC to deposit (e.g. 1000 for $1,000)"),
264
- private_key: z.string().describe("Agent's private key (0x...) for signing the transaction")
265
- })
266
- },
267
- async ({ amount, private_key }) => {
268
- try {
269
- const amountRaw = BigInt(Math.floor(amount * 1e6));
270
- const account = privateKeyToAccount(private_key);
271
- const wallet = createWalletClient({ chain: baseSepolia, transport: http(), account });
272
- const usdcBal = await client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "balanceOf", args: [account.address] });
273
- if (usdcBal < amountRaw) {
274
- return error(`Insufficient USDC. Have ${fmtUSDC(usdcBal)}, need ${fmtUSDC(amountRaw)}`);
275
- }
276
- const allowance = await client.readContract({ address: ADDR.usdc, abi: ERC20_ABI, functionName: "allowance", args: [account.address, ADDR.vault] });
277
- if (allowance < amountRaw) {
278
- const approveTx = await wallet.writeContract({
279
- address: ADDR.usdc,
280
- abi: ERC20_ABI,
281
- functionName: "approve",
282
- args: [ADDR.vault, 2n ** 256n - 1n],
283
- chain: baseSepolia,
284
- account
285
- });
286
- await client.waitForTransactionReceipt({ hash: approveTx });
287
- }
288
- const sharesPreview = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewDeposit", args: [amountRaw] });
289
- const tx = await wallet.writeContract({
290
- address: ADDR.vault,
291
- abi: VAULT_ABI,
292
- functionName: "deposit",
293
- args: [amountRaw],
294
- chain: baseSepolia,
295
- account
296
- });
297
- const receipt = await client.waitForTransactionReceipt({ hash: tx });
298
- return object({
299
- status: "SUCCESS",
300
- deposited_usdc: amount.toString(),
301
- shares_received: fmtUSDC(sharesPreview),
302
- tx_hash: tx,
303
- block: Number(receipt.blockNumber),
304
- gas_used: Number(receipt.gasUsed),
305
- explorer: `https://base-sepolia.blockscout.com/tx/${tx}`
306
- });
307
- } catch (e) {
308
- return error("Deposit failed: " + e.message);
309
- }
310
- }
311
- );
312
- server.tool(
313
- {
314
- name: "arcis_withdraw",
315
- description: "Withdraw USDC from the Arcis vault by redeeming raUSDC shares. Use withdraw_all to redeem entire position.",
316
- schema: z.object({
317
- shares: z.number().positive().optional().describe("Amount of raUSDC shares to redeem (omit to withdraw all)"),
318
- private_key: z.string().describe("Agent's private key (0x...) for signing the transaction"),
319
- withdraw_all: z.boolean().optional().describe("Set to true to withdraw entire position")
320
- })
321
- },
322
- async ({ shares, private_key, withdraw_all }) => {
323
- try {
324
- const account = privateKeyToAccount(private_key);
325
- const wallet = createWalletClient({ chain: baseSepolia, transport: http(), account });
326
- let sharesRaw;
327
- if (withdraw_all) {
328
- sharesRaw = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "balanceOf", args: [account.address] });
329
- if (sharesRaw === 0n) return error("No shares to withdraw");
330
- } else if (shares) {
331
- sharesRaw = BigInt(Math.floor(shares * 1e6));
332
- } else {
333
- return error("Provide either shares amount or set withdraw_all to true");
334
- }
335
- const usdcPreview = await client.readContract({ address: ADDR.vault, abi: VAULT_ABI, functionName: "previewWithdraw", args: [sharesRaw] });
336
- const tx = await wallet.writeContract({
337
- address: ADDR.vault,
338
- abi: VAULT_ABI,
339
- functionName: "withdraw",
340
- args: [sharesRaw],
341
- chain: baseSepolia,
342
- account
343
- });
344
- const receipt = await client.waitForTransactionReceipt({ hash: tx });
345
- return object({
346
- status: "SUCCESS",
347
- shares_redeemed: fmtUSDC(sharesRaw),
348
- usdc_received: fmtUSDC(usdcPreview),
349
- tx_hash: tx,
350
- block: Number(receipt.blockNumber),
351
- explorer: `https://base-sepolia.blockscout.com/tx/${tx}`
352
- });
353
- } catch (e) {
354
- return error("Withdraw failed: " + e.message);
355
- }
356
- }
357
- );
358
- server.resource(
359
- {
360
- uri: "arcis://protocol-info",
361
- name: "Arcis Protocol Info",
362
- description: "Overview of Arcis Protocol \u2014 what it is, how it works, and how agents interact with it",
363
- mimeType: "text/markdown"
364
- },
365
- async () => markdown(`# Arcis Protocol
366
-
367
- **The citadel of agent capital.**
368
-
369
- Arcis builds financial infrastructure for autonomous AI agents: yield-bearing vaults, identity-aware credit lines, and revenue bonds. Deployed on Base.
370
-
371
- ## ATI Standard (Agent Treasury Interface)
372
-
373
- Three functions. Any agent framework.
374
-
375
- - \`deposit(uint256 amount) \u2192 uint256 shares\` \u2014 Deposit USDC, receive yield-bearing raUSDC
376
- - \`withdraw(uint256 shares) \u2192 uint256 amount\` \u2014 Redeem raUSDC for USDC + accrued yield
377
- - \`balance(address agent) \u2192 uint256 value\` \u2014 Check position value in USDC
378
-
379
- ## Products
380
-
381
- 1. **Agent Vaults** \u2014 ERC-4626 vaults where agents park idle USDC. Yield via Aave/Morpho strategies. Management fee: 2% on yield.
382
- 2. **Agent Credit** \u2014 ERC-8004 reputation-aware lending. 5 tiers from 200% to 115% collateral based on on-chain identity score.
383
- 3. **Revenue Bonds** \u2014 Agents with consistent revenue issue tokenized bonds. Human investors buy fixed yield.
384
-
385
- ## Links
386
-
387
- - Website: https://arcis.money
388
- - Dashboard: https://arcis.money/dashboard
389
- - GitHub: https://github.com/Arcis-Protocol
390
- - Telegram: https://t.me/arcisprotocol
391
- - X: https://x.com/ArcisProtocol
392
- `)
393
- );
394
- server.listen();
5
+ (void 0).listen();
package/dist/remote.js ADDED
@@ -0,0 +1,6 @@
1
+ import "./chunk-6OFSQEDB.js";
2
+
3
+ // src/remote.ts
4
+ var PORT = parseInt(process.env.PORT || "3001");
5
+ (void 0).listen(PORT);
6
+ console.log(`Arcis MCP Server listening on http://localhost:${PORT}/mcp`);
package/dist/server.js ADDED
@@ -0,0 +1 @@
1
+ import "./chunk-6OFSQEDB.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcisprotocol/mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Arcis Protocol MCP Server — connect any AI agent to DeFi vaults in one tool call",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,9 +12,11 @@
12
12
  "README.md"
13
13
  ],
14
14
  "scripts": {
15
- "build": "tsup src/index.ts --format esm --clean",
15
+ "build": "tsup src/index.ts src/remote.ts src/server.ts --format esm --clean",
16
16
  "dev": "tsx src/index.ts",
17
+ "dev:remote": "tsx src/remote.ts",
17
18
  "start": "node dist/index.js",
19
+ "start:remote": "node dist/remote.js",
18
20
  "prepublishOnly": "npm run build"
19
21
  },
20
22
  "keywords": ["arcis", "mcp", "model-context-protocol", "defi", "ai-agents", "vault", "base"],