Skip to content

Commit 147a75f

Browse files
author
azeth-sync[bot]
committed
v0.2.5: sync from monorepo 2026-03-07
1 parent ed48d37 commit 147a75f

7 files changed

Lines changed: 49 additions & 39 deletions

File tree

README.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
MCP (Model Context Protocol) server for Azeth -- the trust, discovery, and payment layer for the machine economy. Provides 32 tools for AI agents to create accounts, make payments, discover services, manage reputation, and communicate via XMTP.
1111

12-
## Setup
12+
## Zero-Config Setup
13+
14+
No API keys required. A private key is auto-generated and persisted at `~/.azeth/key`. Gas is sponsored automatically.
1315

1416
### Claude Desktop
1517

@@ -20,11 +22,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
2022
"mcpServers": {
2123
"azeth": {
2224
"command": "npx",
23-
"args": ["@azeth/mcp-server"],
24-
"env": {
25-
"AZETH_PRIVATE_KEY": "0x...",
26-
"PIMLICO_API_KEY": "your-pimlico-api-key"
27-
}
25+
"args": ["@azeth/mcp-server"]
2826
}
2927
}
3028
}
@@ -39,27 +37,26 @@ Add to `.claude/settings.json` in your project:
3937
"mcpServers": {
4038
"azeth": {
4139
"command": "npx",
42-
"args": ["@azeth/mcp-server"],
43-
"env": {
44-
"AZETH_PRIVATE_KEY": "0x...",
45-
"PIMLICO_API_KEY": "your-pimlico-api-key"
46-
}
40+
"args": ["@azeth/mcp-server"]
4741
}
4842
}
4943
}
5044
```
5145

52-
### Local Development
46+
Then ask Claude: *"Create me a smart account called PriceFeedBot"* -- that's it.
47+
48+
### With Your Own Key
49+
50+
For production or to use an existing key, add environment variables:
5351

5452
```json
5553
{
5654
"mcpServers": {
5755
"azeth": {
58-
"command": "node",
59-
"args": ["path/to/Azeth/packages/mcp-server/dist/index.js"],
56+
"command": "npx",
57+
"args": ["@azeth/mcp-server"],
6058
"env": {
61-
"AZETH_PRIVATE_KEY": "0x...",
62-
"PIMLICO_API_KEY": "your-pimlico-api-key"
59+
"AZETH_PRIVATE_KEY": "0x..."
6360
}
6461
}
6562
}
@@ -68,14 +65,17 @@ Add to `.claude/settings.json` in your project:
6865

6966
## Environment Variables
7067

68+
All optional. The server works with zero configuration on testnet.
69+
7170
| Variable | Required | Description |
7271
|---|---|---|
73-
| `AZETH_PRIVATE_KEY` | Yes | Account owner's private key (0x-prefixed hex) |
74-
| `PIMLICO_API_KEY` | Yes* | Pimlico bundler/paymaster API key (*required for state-changing operations) |
75-
| `AZETH_CHAIN` | No | `"baseSepolia"` or `"base"` (default: `baseSepolia`) |
76-
| `AZETH_RPC_URL` | No | Custom RPC endpoint |
72+
| `AZETH_PRIVATE_KEY` | No | Account owner's private key. Auto-generated and saved to `~/.azeth/key` if not set. |
73+
| `PIMLICO_API_KEY` | No | Pimlico bundler API key. Falls back to Azeth server bundler proxy if not set. |
74+
| `AZETH_CHAIN` | No | `"baseSepolia"`, `"ethereumSepolia"`, `"base"`, or `"ethereum"` (default: `baseSepolia`) |
75+
| `AZETH_RPC_URL_BASE_SEPOLIA` | No | Custom RPC endpoint (per-chain: `AZETH_RPC_URL_BASE`, `AZETH_RPC_URL_ETH_SEPOLIA`, `AZETH_RPC_URL_ETHEREUM`) |
7776
| `AZETH_SERVER_URL` | No | Azeth API server URL (default: `https://api.azeth.ai`) |
78-
| `XMTP_ENCRYPTION_KEY` | No | For XMTP messaging tools |
77+
| `AZETH_GUARDIAN_KEY` | No | Separate guardian key for co-signing high-value operations |
78+
| `XMTP_ENCRYPTION_KEY` | No | For persistent XMTP messaging across restarts |
7979

8080
## Tools (32)
8181

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azeth/mcp-server",
3-
"version": "0.2.4",
3+
"version": "0.2.5",
44
"mcpName": "io.github.azeth-protocol/mcp-server",
55
"type": "module",
66
"description": "MCP server for the Azeth trust infrastructure — smart accounts, payments, reputation, and discovery tools for AI agents",
@@ -41,8 +41,8 @@
4141
"clean": "rm -rf dist"
4242
},
4343
"dependencies": {
44-
"@azeth/common": "^0.2.4",
45-
"@azeth/sdk": "^0.2.4",
44+
"@azeth/common": "^0.2.5",
45+
"@azeth/sdk": "^0.2.5",
4646
"@modelcontextprotocol/sdk": "^1.0.0",
4747
"dotenv": "^16.4.0",
4848
"viem": "^2.21.0",

src/tools/account.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ export function registerAccountTools(server: McpServer): void {
5555
'',
5656
'Returns: The deployed smart account address, trust registry token ID, and transaction hash.',
5757
'',
58+
'Gas is automatically sponsored — no ETH required. The SDK uses a gasless relay (EIP-712 signature)',
59+
'so the account can be created without any pre-funding. On testnet, USDC is also auto-funded.',
60+
'',
5861
'Guardian: By default, the guardian is derived from AZETH_GUARDIAN_KEY env var. If not set, falls back to self-guardian (owner address).',
5962
'For production, always use a separate guardian key. Set AZETH_GUARDIAN_KEY in your .env file.',
6063
'',
61-
'Note: This is a state-changing operation that deploys contracts on-chain. It requires ETH for gas.',
62-
'The owner private key is read from the AZETH_PRIVATE_KEY environment variable.',
63-
'',
6464
'Example: { "name": "PriceFeedBot", "entityType": "service", "description": "Real-time crypto price data", "capabilities": ["price-feed", "market-data"] }',
6565
].join('\n'),
6666
inputSchema: z.object({
@@ -151,6 +151,8 @@ export function registerAccountTools(server: McpServer): void {
151151
TOKENS[chain].WETH,
152152
];
153153

154+
const serverUrl = process.env['AZETH_SERVER_URL'] ?? 'https://api.azeth.ai';
155+
154156
const result = await client.createAccount({
155157
owner: client.address,
156158
guardrails: {
@@ -171,7 +173,6 @@ export function registerAccountTools(server: McpServer): void {
171173
},
172174
});
173175

174-
const serverUrl = process.env['AZETH_SERVER_URL'] ?? 'https://api.azeth.ai';
175176
const tokenIdStr = result.tokenId.toString();
176177
const badgeUrl = `${serverUrl}/badge/${tokenIdStr}`;
177178
const profileUrl = `https://azeth.ai/agent/${result.account}`;
@@ -199,6 +200,13 @@ export function registerAccountTools(server: McpServer): void {
199200
{ txHash: result.txHash },
200201
);
201202
} catch (err) {
203+
if (err instanceof Error && err.message.includes('insufficient funds')) {
204+
return error(
205+
'INSUFFICIENT_BALANCE',
206+
'Account deployment failed: gasless relay unavailable and your EOA has no ETH for direct deployment.',
207+
'The relay at api.azeth.ai may be down or rate-limited. Try again later, or send a small amount of ETH to your EOA address for direct deployment.',
208+
);
209+
}
202210
return handleError(err);
203211
} finally {
204212
try { await client?.destroy(); } catch (e) { process.stderr.write(`[azeth-mcp] destroy error: ${e instanceof Error ? e.message : String(e)}\n`); }

src/tools/registry.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { z } from 'zod';
22
import { hexToString } from 'viem';
33
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
44
import { discoverServicesWithFallback, getRegistryEntry } from '@azeth/sdk';
5-
import { AZETH_CONTRACTS, ERC8004_REGISTRY, formatTokenAmount, CATALOG_MAX_ENTRIES, CATALOG_MAX_PATH_LENGTH } from '@azeth/common';
5+
import { AZETH_CONTRACTS, ERC8004_REGISTRY, RPC_ENV_KEYS, SUPPORTED_CHAINS, formatTokenAmount, CATALOG_MAX_ENTRIES, CATALOG_MAX_PATH_LENGTH } from '@azeth/common';
66
import type { CatalogEntry, CatalogMethod } from '@azeth/common';
77
import { TrustRegistryModuleAbi, ReputationModuleAbi } from '@azeth/common/abis';
88
import { createClient, resolveChain, resolveViemChain, validateAddress } from '../utils/client.js';
@@ -287,7 +287,7 @@ export function registerRegistryTools(server: McpServer): void {
287287
// Create a public client for the on-chain fallback
288288
const { createPublicClient, http } = await import('viem');
289289
const chain = resolveViemChain(chainName);
290-
const rpcUrl = process.env['AZETH_RPC_URL'];
290+
const rpcUrl = process.env[RPC_ENV_KEYS[chainName]] ?? SUPPORTED_CHAINS[chainName].rpcDefault;
291291
const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
292292

293293
const result = await discoverServicesWithFallback(
@@ -444,7 +444,7 @@ export function registerRegistryTools(server: McpServer): void {
444444
// Create a public client for on-chain reads
445445
const { createPublicClient, http } = await import('viem');
446446
const viemChain = resolveViemChain(chainName);
447-
const rpcUrl = process.env['AZETH_RPC_URL'];
447+
const rpcUrl = process.env[RPC_ENV_KEYS[chainName]] ?? SUPPORTED_CHAINS[chainName].rpcDefault;
448448
const publicClient = createPublicClient({ chain: viemChain, transport: http(rpcUrl) });
449449

450450
// Resolve tokenId from address if needed

src/tools/reputation.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
33
import { createClient, resolveChain, resolveViemChain, validateAddress } from '../utils/client.js';
44
import { success, error, handleError, formatUSD } from '../utils/response.js';
55
import { ReputationModuleAbi, TrustRegistryModuleAbi } from '@azeth/common/abis';
6-
import { AzethError, AZETH_CONTRACTS, formatTokenAmount } from '@azeth/common';
6+
import { AzethError, AZETH_CONTRACTS, RPC_ENV_KEYS, SUPPORTED_CHAINS, formatTokenAmount } from '@azeth/common';
77

88
/** Maximum uint256 value for on-chain IDs */
99
const MAX_UINT256 = (1n << 256n) - 1n;
@@ -151,7 +151,7 @@ export function registerReputationTools(server: McpServer): void {
151151

152152
const resolved = resolveChain(args.chain);
153153
const chain = resolveViemChain(resolved);
154-
const rpcUrl = process.env['AZETH_RPC_URL'];
154+
const rpcUrl = process.env[RPC_ENV_KEYS[resolved]] ?? SUPPORTED_CHAINS[resolved].rpcDefault;
155155

156156
const publicClient = createPublicClient({
157157
chain,
@@ -278,7 +278,7 @@ export function registerReputationTools(server: McpServer): void {
278278

279279
const resolved = resolveChain(args.chain);
280280
const chain = resolveViemChain(resolved);
281-
const rpcUrl = process.env['AZETH_RPC_URL'];
281+
const rpcUrl = process.env[RPC_ENV_KEYS[resolved]] ?? SUPPORTED_CHAINS[resolved].rpcDefault;
282282

283283
const publicClient = createPublicClient({
284284
chain,

src/utils/client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AzethKit, type AzethKitConfig } from '@azeth/sdk';
2-
import { AzethError, resolveChainAlias, resolveViemChain, type XMTPConfig, type SupportedChainName } from '@azeth/common';
2+
import { AzethError, resolveChainAlias, resolveViemChain, RPC_ENV_KEYS, type XMTPConfig, type SupportedChainName } from '@azeth/common';
33

44
/** Resolve a chain argument to a canonical SupportedChainName.
55
* Resolution order: explicit arg > AZETH_CHAIN env > 'baseSepolia' default.
@@ -73,7 +73,9 @@ export async function createClient(
7373
guardianAutoSign,
7474
};
7575

76-
const rpcUrl = process.env['AZETH_RPC_URL'];
76+
// SDK resolves RPC from SUPPORTED_CHAINS[chain].rpcDefault when config.rpcUrl is not set.
77+
// Per-chain env vars (AZETH_RPC_URL_BASE_SEPOLIA, etc.) override the default.
78+
const rpcUrl = process.env[RPC_ENV_KEYS[resolvedChain]];
7779
if (rpcUrl) {
7880
config.rpcUrl = rpcUrl;
7981
}

src/utils/resolve.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { AzethKit } from '@azeth/sdk';
2-
import { AzethError, AZETH_CONTRACTS, ERC8004_REGISTRY } from '@azeth/common';
2+
import { AzethError, AZETH_CONTRACTS, ERC8004_REGISTRY, RPC_ENV_KEYS, SUPPORTED_CHAINS } from '@azeth/common';
33
import { TrustRegistryModuleAbi, AzethOracleAbi } from '@azeth/common/abis';
44
import { validateAddress, resolveChain, resolveViemChain } from './client.js';
55

@@ -128,7 +128,7 @@ export async function resolveAddress(
128128
try {
129129
const { createPublicClient, http } = await import('viem');
130130
const viemChain = resolveViemChain(chain);
131-
const rpcUrl = process.env['AZETH_RPC_URL'];
131+
const rpcUrl = process.env[RPC_ENV_KEYS[chain]] ?? SUPPORTED_CHAINS[chain].rpcDefault;
132132
const pubClient = createPublicClient({ chain: viemChain, transport: http(rpcUrl) });
133133

134134
const tokenId = BigInt(tokenMatch[1]!);
@@ -275,7 +275,7 @@ async function resolveNameOnChain(
275275
const { createPublicClient, http } = await import('viem');
276276
const chain = resolveChain(process.env['AZETH_CHAIN']);
277277
const viemChain = resolveViemChain(chain);
278-
const rpcUrl = process.env['AZETH_RPC_URL'];
278+
const rpcUrl = process.env[RPC_ENV_KEYS[chain]] ?? SUPPORTED_CHAINS[chain].rpcDefault;
279279

280280
const registryAddress = ERC8004_REGISTRY[chain];
281281
const oracleAddress = AZETH_CONTRACTS[chain]?.priceOracle;

0 commit comments

Comments
 (0)