@agent-shield/mcp 0.2.2 → 0.4.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/README.md CHANGED
@@ -16,7 +16,7 @@ npx @agent-shield/mcp
16
16
 
17
17
  | Variable | Required | Default | Description |
18
18
  |----------|----------|---------|-------------|
19
- | `AGENTSHIELD_WALLET_PATH` | Yes | — | Path to Solana keypair JSON (vault owner) |
19
+ | `AGENTSHIELD_WALLET_PATH` | No | — | Path to Solana keypair JSON (vault owner). Not required — server starts in setup mode without it. |
20
20
  | `AGENTSHIELD_RPC_URL` | No | devnet | Solana RPC endpoint URL |
21
21
  | `AGENTSHIELD_AGENT_KEYPAIR_PATH` | No | — | Path to agent keypair JSON (needed for swap/position tools) |
22
22
 
@@ -57,7 +57,16 @@ Add to `.cursor/mcp.json` in your project:
57
57
  }
58
58
  ```
59
59
 
60
- ## Tools (12)
60
+ ## Tools (22)
61
+
62
+ ### Setup & Onboarding (always available — no wallet required)
63
+
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `shield_setup_status` | Check current setup status — which security tiers are active |
67
+ | `shield_configure` | Set up AgentShield with any tier (1=Shield, 2=TEE, 3=Vault) |
68
+ | `shield_fund_wallet` | Generate funding links (Blink URL, Solana Pay, raw address) |
69
+ | `shield_upgrade_tier` | Upgrade from current tier to a higher one |
61
70
 
62
71
  ### Read-Only
63
72
 
@@ -65,6 +74,7 @@ Add to `.cursor/mcp.json` in your project:
65
74
  |------|-------------|
66
75
  | `shield_check_vault` | Check vault status, owner, agent, and policy configuration |
67
76
  | `shield_check_spending` | Check rolling 24h spending and recent transaction history |
77
+ | `shield_check_pending_policy` | Check pending timelocked policy update status |
68
78
 
69
79
  ### Owner-Signed (Write)
70
80
 
@@ -75,8 +85,12 @@ Add to `.cursor/mcp.json` in your project:
75
85
  | `shield_withdraw` | Withdraw tokens from a vault |
76
86
  | `shield_register_agent` | Register an agent signing key |
77
87
  | `shield_update_policy` | Update spending caps, token/protocol allowlists, leverage limits |
88
+ | `shield_queue_policy_update` | Queue a timelocked policy change |
89
+ | `shield_apply_pending_policy` | Apply a queued policy change after timelock expires |
90
+ | `shield_cancel_pending_policy` | Cancel a queued policy change |
78
91
  | `shield_revoke_agent` | Emergency kill switch — freezes vault immediately |
79
92
  | `shield_reactivate_vault` | Unfreeze a vault, optionally with a new agent |
93
+ | `shield_provision` | Provision a vault via Solana Actions |
80
94
 
81
95
  ### Agent-Signed (Requires `AGENTSHIELD_AGENT_KEYPAIR_PATH`)
82
96
 
@@ -85,6 +99,7 @@ Add to `.cursor/mcp.json` in your project:
85
99
  | `shield_execute_swap` | Execute a Jupiter token swap through the vault |
86
100
  | `shield_open_position` | Open a Flash Trade leveraged perpetual position |
87
101
  | `shield_close_position` | Close a Flash Trade perpetual position |
102
+ | `shield_agent_transfer` | Transfer tokens to an allowlisted destination |
88
103
 
89
104
  ## Resources (3)
90
105
 
@@ -105,7 +120,7 @@ pnpm install
105
120
  # Build
106
121
  pnpm build
107
122
 
108
- # Run tests (82 tests)
123
+ # Run tests (107 tests)
109
124
  pnpm test
110
125
 
111
126
  # Smoke test
@@ -117,7 +132,8 @@ AGENTSHIELD_WALLET_PATH=~/.config/solana/id.json node dist/index.js
117
132
  - **Transport**: stdio only (local subprocess of the AI tool)
118
133
  - **Credentials**: Environment variables (keypair file paths)
119
134
  - **SDK**: Wraps `AgentShieldClient` from `@agent-shield/sdk` — every tool delegates to a client method
120
- - **Error handling**: All 37 Anchor error codes mapped to human-readable messages with actionable suggestions
135
+ - **Setup mode**: Starts without a wallet only setup/onboarding tools available until configured
136
+ - **Error handling**: All 40 Anchor error codes (6000–6039) mapped to human-readable messages with actionable suggestions
121
137
 
122
138
  ## Support
123
139
 
package/dist/config.d.ts CHANGED
@@ -2,6 +2,61 @@ import { Keypair } from "@solana/web3.js";
2
2
  import { AgentShieldClient } from "@agent-shield/sdk";
3
3
  /** Supported custody providers for MCP server. */
4
4
  export type McpCustodyProvider = "crossmint" | "turnkey" | "privy";
5
+ export interface ShieldLayerConfig {
6
+ shield: {
7
+ enabled: boolean;
8
+ dailyCapUsd: number;
9
+ allowedProtocols: string[];
10
+ maxLeverageBps: number;
11
+ rateLimit: number;
12
+ };
13
+ tee: {
14
+ enabled: boolean;
15
+ locator: string | null;
16
+ publicKey: string | null;
17
+ };
18
+ vault: {
19
+ enabled: boolean;
20
+ address: string | null;
21
+ owner: string | null;
22
+ vaultId: string | null;
23
+ };
24
+ }
25
+ export interface ShieldLocalConfig {
26
+ version: 1;
27
+ layers: ShieldLayerConfig;
28
+ wallet: {
29
+ type: "keypair" | "crossmint";
30
+ path: string | null;
31
+ publicKey: string;
32
+ };
33
+ network: "devnet" | "mainnet-beta";
34
+ template: "conservative" | "moderate" | "aggressive";
35
+ configuredAt: string;
36
+ }
37
+ /** Canonical config directory. */
38
+ export declare function getConfigDir(): string;
39
+ /** Canonical config file path. */
40
+ export declare function getConfigPath(): string;
41
+ /**
42
+ * Load local shield config from ~/.agentshield/config.json.
43
+ * Falls back to env vars for backwards compatibility with existing MCP installs.
44
+ * Returns null if neither config file nor env vars exist.
45
+ */
46
+ export declare function loadShieldConfig(): ShieldLocalConfig | null;
47
+ /**
48
+ * Save local shield config to ~/.agentshield/config.json.
49
+ * Creates the directory if needed. Sets file permissions to 0600.
50
+ */
51
+ export declare function saveShieldConfig(config: ShieldLocalConfig): void;
52
+ /**
53
+ * Returns true if AgentShield is configured (config file exists or env vars set).
54
+ */
55
+ export declare function isConfigured(): boolean;
56
+ /**
57
+ * Returns the current tier number based on enabled layers.
58
+ */
59
+ export declare function getCurrentTier(config: ShieldLocalConfig): 1 | 2 | 3;
5
60
  export interface McpConfig {
6
61
  /** Path to owner wallet keypair JSON. Not needed when using custody. */
7
62
  walletPath?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,kDAAkD;AAClD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,IAAI,SAAS,CAgCtC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,iBAAiB,CAWjE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACpE,SAAS,EAAE,OAAO,iBAAiB,EAAE,SAAS,CAAC;IAC/C,eAAe,EAAE,QAAQ,CAAC;CAC3B,CAAC,CAuCD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAQ3D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,OAAO,EAAiB,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAKtD,kDAAkD;AAClD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAInE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE;QACN,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,GAAG,EAAE;QACH,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE;QACN,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;QAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,EAAE,QAAQ,GAAG,cAAc,CAAC;IACnC,QAAQ,EAAE,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;IACrD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,kCAAkC;AAClC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,kCAAkC;AAClC,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,GAAG,IAAI,CAgD3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAShE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAInE;AAED,MAAM,WAAW,SAAS;IACxB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,IAAI,SAAS,CAgCtC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,iBAAiB,CAWjE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACpE,SAAS,EAAE,OAAO,iBAAiB,EAAE,SAAS,CAAC;IAC/C,eAAe,EAAE,QAAQ,CAAC;CAC3B,CAAC,CAuCD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAQ3D"}
package/dist/config.js CHANGED
@@ -33,6 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getConfigDir = getConfigDir;
37
+ exports.getConfigPath = getConfigPath;
38
+ exports.loadShieldConfig = loadShieldConfig;
39
+ exports.saveShieldConfig = saveShieldConfig;
40
+ exports.isConfigured = isConfigured;
41
+ exports.getCurrentTier = getCurrentTier;
36
42
  exports.loadConfig = loadConfig;
37
43
  exports.loadKeypair = loadKeypair;
38
44
  exports.createClient = createClient;
@@ -42,6 +48,99 @@ const web3_js_1 = require("@solana/web3.js");
42
48
  const anchor_1 = require("@coral-xyz/anchor");
43
49
  const sdk_1 = require("@agent-shield/sdk");
44
50
  const fs = __importStar(require("fs"));
51
+ const path = __importStar(require("path"));
52
+ const os = __importStar(require("os"));
53
+ /** Canonical config directory. */
54
+ function getConfigDir() {
55
+ return path.join(os.homedir(), ".agentshield");
56
+ }
57
+ /** Canonical config file path. */
58
+ function getConfigPath() {
59
+ return path.join(getConfigDir(), "config.json");
60
+ }
61
+ /**
62
+ * Load local shield config from ~/.agentshield/config.json.
63
+ * Falls back to env vars for backwards compatibility with existing MCP installs.
64
+ * Returns null if neither config file nor env vars exist.
65
+ */
66
+ function loadShieldConfig() {
67
+ const configPath = getConfigPath();
68
+ // Config file takes precedence
69
+ if (fs.existsSync(configPath)) {
70
+ try {
71
+ const raw = fs.readFileSync(configPath, "utf-8");
72
+ return JSON.parse(raw);
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
78
+ // Fall back to env vars (backwards compatible with existing installs)
79
+ const walletPath = process.env.AGENTSHIELD_WALLET_PATH;
80
+ if (walletPath) {
81
+ try {
82
+ const kp = loadKeypair(walletPath);
83
+ return {
84
+ version: 1,
85
+ layers: {
86
+ shield: {
87
+ enabled: true,
88
+ dailyCapUsd: 500,
89
+ allowedProtocols: [],
90
+ maxLeverageBps: 0,
91
+ rateLimit: 60,
92
+ },
93
+ tee: { enabled: false, locator: null, publicKey: null },
94
+ vault: { enabled: false, address: null, owner: null, vaultId: null },
95
+ },
96
+ wallet: {
97
+ type: "keypair",
98
+ path: walletPath,
99
+ publicKey: kp.publicKey.toBase58(),
100
+ },
101
+ network: (process.env.AGENTSHIELD_RPC_URL?.includes("mainnet")
102
+ ? "mainnet-beta"
103
+ : "devnet"),
104
+ template: "conservative",
105
+ configuredAt: new Date().toISOString(),
106
+ };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ /**
115
+ * Save local shield config to ~/.agentshield/config.json.
116
+ * Creates the directory if needed. Sets file permissions to 0600.
117
+ */
118
+ function saveShieldConfig(config) {
119
+ const dir = getConfigDir();
120
+ if (!fs.existsSync(dir)) {
121
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
122
+ }
123
+ const configPath = getConfigPath();
124
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), {
125
+ mode: 0o600,
126
+ });
127
+ }
128
+ /**
129
+ * Returns true if AgentShield is configured (config file exists or env vars set).
130
+ */
131
+ function isConfigured() {
132
+ return loadShieldConfig() !== null;
133
+ }
134
+ /**
135
+ * Returns the current tier number based on enabled layers.
136
+ */
137
+ function getCurrentTier(config) {
138
+ if (config.layers.vault.enabled)
139
+ return 3;
140
+ if (config.layers.tee.enabled)
141
+ return 2;
142
+ return 1;
143
+ }
45
144
  function loadConfig() {
46
145
  const rpcUrl = process.env.AGENTSHIELD_RPC_URL || (0, web3_js_1.clusterApiUrl)("devnet");
47
146
  const agentKeypairPath = process.env.AGENTSHIELD_AGENT_KEYPAIR_PATH || undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -24,10 +24,17 @@ const apply_pending_policy_1 = require("./tools/apply-pending-policy");
24
24
  const cancel_pending_policy_1 = require("./tools/cancel-pending-policy");
25
25
  const check_pending_policy_1 = require("./tools/check-pending-policy");
26
26
  const agent_transfer_1 = require("./tools/agent-transfer");
27
+ // Setup & onboarding tools (work without SDK client)
28
+ const setup_status_1 = require("./tools/setup-status");
29
+ const configure_1 = require("./tools/configure");
30
+ const fund_wallet_1 = require("./tools/fund-wallet");
31
+ const upgrade_tier_1 = require("./tools/upgrade-tier");
27
32
  // Resources
28
33
  const policy_1 = require("./resources/policy");
29
34
  const spending_1 = require("./resources/spending");
30
35
  const activity_1 = require("./resources/activity");
36
+ const NOT_CONFIGURED_MSG = "AgentShield is not configured yet. " +
37
+ 'Use shield_setup_status to check status, or ask me to "Set up AgentShield".';
31
38
  /**
32
39
  * Helper to register a tool with the MCP server.
33
40
  * Uses `any` cast to work around zod version mismatch between
@@ -40,28 +47,98 @@ function registerTool(server, name, description, schema, handler) {
40
47
  async function main() {
41
48
  // All logging to stderr — stdout is reserved for JSON-RPC
42
49
  console.error("[agent-shield-mcp] Starting...");
43
- let config;
50
+ // Try to load config, but don't exit if it fails — run in setup mode
51
+ let config = null;
52
+ let client = null;
44
53
  try {
45
54
  config = (0, config_1.loadConfig)();
46
- }
47
- catch (error) {
48
- console.error(`[agent-shield-mcp] Configuration error: ${error}`);
49
- process.exit(1);
50
- }
51
- let client;
52
- try {
53
55
  client = (0, config_1.createClient)(config);
56
+ console.error(`[agent-shield-mcp] Connected to ${config.rpcUrl}, ` +
57
+ `wallet: ${client.provider.wallet.publicKey.toBase58()}`);
58
+ }
59
+ catch {
60
+ console.error("[agent-shield-mcp] No wallet configured — running in setup mode. " +
61
+ "Use shield_setup_status or shield_configure to get started.");
54
62
  }
55
- catch (error) {
56
- console.error(`[agent-shield-mcp] Client creation failed: ${error}`);
57
- process.exit(1);
63
+ /**
64
+ * Guard for tools that require a configured SDK client.
65
+ * Returns the "not configured" message if no client is available.
66
+ */
67
+ function requireClient(fn) {
68
+ return async (input) => {
69
+ // Re-check at call time (config may have been created since startup)
70
+ if (!client) {
71
+ try {
72
+ const freshConfig = (0, config_1.loadConfig)();
73
+ client = (0, config_1.createClient)(freshConfig);
74
+ config = freshConfig;
75
+ }
76
+ catch {
77
+ return {
78
+ content: [{ type: "text", text: NOT_CONFIGURED_MSG }],
79
+ };
80
+ }
81
+ }
82
+ return {
83
+ content: [{ type: "text", text: await fn(input) }],
84
+ };
85
+ };
58
86
  }
59
- console.error(`[agent-shield-mcp] Connected to ${config.rpcUrl}, ` +
60
- `wallet: ${client.provider.wallet.publicKey.toBase58()}`);
61
87
  const server = new mcp_js_1.McpServer({
62
88
  name: "agent-shield",
63
89
  version: "0.1.0",
64
90
  });
91
+ // ── Setup & Onboarding Tools (always available) ───────────────
92
+ registerTool(server, "shield_setup_status", "Check the current AgentShield setup status — shows which security tiers are active, wallet, policy, and network. Works even when not configured.", {}, async (input) => ({
93
+ content: [{ type: "text", text: await (0, setup_status_1.setupStatus)(null, input) }],
94
+ }));
95
+ registerTool(server, "shield_configure", "Set up AgentShield with any security tier (1=Shield, 2=Shield+TEE, 3=Shield+TEE+Vault). Generates keypair, provisions TEE, and/or creates vault.", {
96
+ tier: zod_1.z
97
+ .union([zod_1.z.literal(1), zod_1.z.literal(2), zod_1.z.literal(3)])
98
+ .describe("Security tier: 1=Shield, 2=Shield+TEE, 3=Shield+TEE+Vault"),
99
+ template: zod_1.z
100
+ .enum(["conservative", "moderate", "aggressive"])
101
+ .optional()
102
+ .default("conservative")
103
+ .describe("Policy template"),
104
+ dailyCapUsd: zod_1.z.number().optional().describe("Custom daily cap in USD"),
105
+ allowedProtocols: zod_1.z
106
+ .array(zod_1.z.string())
107
+ .optional()
108
+ .describe("Custom protocol IDs (base58)"),
109
+ maxLeverageBps: zod_1.z
110
+ .number()
111
+ .optional()
112
+ .describe("Custom max leverage in BPS"),
113
+ rateLimit: zod_1.z.number().optional().describe("Custom rate limit (tx/min)"),
114
+ network: zod_1.z
115
+ .enum(["devnet", "mainnet-beta"])
116
+ .optional()
117
+ .default("devnet")
118
+ .describe("Solana network"),
119
+ walletPath: zod_1.z
120
+ .string()
121
+ .optional()
122
+ .describe("Path to existing keypair JSON"),
123
+ }, async (input) => ({
124
+ content: [{ type: "text", text: await (0, configure_1.configure)(null, input) }],
125
+ }));
126
+ registerTool(server, "shield_fund_wallet", "Generate funding links (Blink URL, Solana Pay, raw address) for the configured AgentShield wallet.", {
127
+ mint: zod_1.z
128
+ .string()
129
+ .optional()
130
+ .describe("Token mint (base58). Omit for SOL."),
131
+ amount: zod_1.z.string().optional().describe("Amount in human-readable units"),
132
+ }, async (input) => ({
133
+ content: [{ type: "text", text: await (0, fund_wallet_1.fundWallet)(null, input) }],
134
+ }));
135
+ registerTool(server, "shield_upgrade_tier", "Upgrade AgentShield from current tier to a higher one (2=add TEE, 3=add Vault). Preserves existing policy.", {
136
+ targetTier: zod_1.z
137
+ .union([zod_1.z.literal(2), zod_1.z.literal(3)])
138
+ .describe("Target tier: 2=add TEE, 3=add Vault"),
139
+ }, async (input) => ({
140
+ content: [{ type: "text", text: await (0, upgrade_tier_1.upgradeTier)(null, input) }],
141
+ }));
65
142
  // ── Read-Only Tools ──────────────────────────────────────────
66
143
  registerTool(server, "shield_check_vault", "Check the status and policy configuration of an AgentShield vault", {
67
144
  vault: zod_1.z
@@ -75,21 +152,13 @@ async function main() {
75
152
  .string()
76
153
  .optional()
77
154
  .describe("Vault ID number. Used with owner."),
78
- }, async (input) => ({
79
- content: [{ type: "text", text: await (0, check_vault_1.checkVault)(client, input) }],
80
- }));
155
+ }, requireClient((input) => (0, check_vault_1.checkVault)(client, input)));
81
156
  registerTool(server, "shield_check_spending", "Check the rolling 24h spending and recent transactions for a vault", {
82
157
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
83
- }, async (input) => ({
84
- content: [{ type: "text", text: await (0, check_spending_1.checkSpending)(client, input) }],
85
- }));
158
+ }, requireClient((input) => (0, check_spending_1.checkSpending)(client, input)));
86
159
  registerTool(server, "shield_check_pending_policy", "Check if a pending timelocked policy update exists for a vault", {
87
160
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
88
- }, async (input) => ({
89
- content: [
90
- { type: "text", text: await (0, check_pending_policy_1.checkPendingPolicy)(client, input) },
91
- ],
92
- }));
161
+ }, requireClient((input) => (0, check_pending_policy_1.checkPendingPolicy)(client, input)));
93
162
  // ── Owner-Signed Write Tools ────────────────────────────────
94
163
  registerTool(server, "shield_create_vault", "Create a new AgentShield vault with policy configuration", {
95
164
  vaultId: zod_1.z.string().describe("Unique vault ID number"),
@@ -128,29 +197,21 @@ async function main() {
128
197
  .optional()
129
198
  .default(0)
130
199
  .describe("Timelock duration in seconds (0 = immediate policy updates)"),
131
- }, async (input) => ({
132
- content: [{ type: "text", text: await (0, create_vault_1.createVault)(client, input) }],
133
- }));
200
+ }, requireClient((input) => (0, create_vault_1.createVault)(client, input)));
134
201
  registerTool(server, "shield_deposit", "Deposit tokens into an AgentShield vault", {
135
202
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
136
203
  mint: zod_1.z.string().describe("Token mint address (base58)"),
137
204
  amount: zod_1.z.string().describe("Amount in token base units"),
138
- }, async (input) => ({
139
- content: [{ type: "text", text: await (0, deposit_1.deposit)(client, input) }],
140
- }));
205
+ }, requireClient((input) => (0, deposit_1.deposit)(client, input)));
141
206
  registerTool(server, "shield_withdraw", "Withdraw tokens from an AgentShield vault (owner-only)", {
142
207
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
143
208
  mint: zod_1.z.string().describe("Token mint address (base58)"),
144
209
  amount: zod_1.z.string().describe("Amount in token base units"),
145
- }, async (input) => ({
146
- content: [{ type: "text", text: await (0, withdraw_1.withdraw)(client, input) }],
147
- }));
210
+ }, requireClient((input) => (0, withdraw_1.withdraw)(client, input)));
148
211
  registerTool(server, "shield_register_agent", "Register an agent signing key to a vault", {
149
212
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
150
213
  agent: zod_1.z.string().describe("Agent public key to register (base58)"),
151
- }, async (input) => ({
152
- content: [{ type: "text", text: await (0, register_agent_1.registerAgent)(client, input) }],
153
- }));
214
+ }, requireClient((input) => (0, register_agent_1.registerAgent)(client, input)));
154
215
  registerTool(server, "shield_update_policy", "Update the policy configuration for a vault (owner-only)", {
155
216
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
156
217
  dailySpendingCapUsd: zod_1.z
@@ -190,9 +251,7 @@ async function main() {
190
251
  .number()
191
252
  .optional()
192
253
  .describe("New timelock duration in seconds"),
193
- }, async (input) => ({
194
- content: [{ type: "text", text: await (0, update_policy_1.updatePolicy)(client, input) }],
195
- }));
254
+ }, requireClient((input) => (0, update_policy_1.updatePolicy)(client, input)));
196
255
  registerTool(server, "shield_queue_policy_update", "Queue a timelocked policy change (required when timelock_duration > 0)", {
197
256
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
198
257
  dailySpendingCapUsd: zod_1.z
@@ -232,37 +291,23 @@ async function main() {
232
291
  .number()
233
292
  .optional()
234
293
  .describe("New developer fee rate (max 50)"),
235
- }, async (input) => ({
236
- content: [{ type: "text", text: await (0, queue_policy_update_1.queuePolicyUpdate)(client, input) }],
237
- }));
294
+ }, requireClient((input) => (0, queue_policy_update_1.queuePolicyUpdate)(client, input)));
238
295
  registerTool(server, "shield_apply_pending_policy", "Apply a pending timelocked policy update after timelock expires", {
239
296
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
240
- }, async (input) => ({
241
- content: [
242
- { type: "text", text: await (0, apply_pending_policy_1.applyPendingPolicy)(client, input) },
243
- ],
244
- }));
297
+ }, requireClient((input) => (0, apply_pending_policy_1.applyPendingPolicy)(client, input)));
245
298
  registerTool(server, "shield_cancel_pending_policy", "Cancel a pending timelocked policy update before it takes effect", {
246
299
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
247
- }, async (input) => ({
248
- content: [
249
- { type: "text", text: await (0, cancel_pending_policy_1.cancelPendingPolicy)(client, input) },
250
- ],
251
- }));
300
+ }, requireClient((input) => (0, cancel_pending_policy_1.cancelPendingPolicy)(client, input)));
252
301
  registerTool(server, "shield_revoke_agent", "Emergency kill switch — revokes agent and freezes vault immediately", {
253
302
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
254
- }, async (input) => ({
255
- content: [{ type: "text", text: await (0, revoke_agent_1.revokeAgent)(client, input) }],
256
- }));
303
+ }, requireClient((input) => (0, revoke_agent_1.revokeAgent)(client, input)));
257
304
  registerTool(server, "shield_reactivate_vault", "Reactivate a frozen vault, optionally with a new agent", {
258
305
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
259
306
  newAgent: zod_1.z
260
307
  .string()
261
308
  .optional()
262
309
  .describe("Optional new agent public key (base58)"),
263
- }, async (input) => ({
264
- content: [{ type: "text", text: await (0, reactivate_vault_1.reactivateVault)(client, input) }],
265
- }));
310
+ }, requireClient((input) => (0, reactivate_vault_1.reactivateVault)(client, input)));
266
311
  // ── Agent-Signed Tools ──────────────────────────────────────
267
312
  registerTool(server, "shield_agent_transfer", "Transfer tokens from a vault to an allowed destination (agent-signed)", {
268
313
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
@@ -271,9 +316,7 @@ async function main() {
271
316
  .describe("Destination wallet address (base58). Must be in allowed_destinations if configured."),
272
317
  mint: zod_1.z.string().describe("Token mint address (base58)"),
273
318
  amount: zod_1.z.string().describe("Amount in token base units"),
274
- }, async (input) => ({
275
- content: [{ type: "text", text: await (0, agent_transfer_1.agentTransfer)(client, input) }],
276
- }));
319
+ }, requireClient((input) => (0, agent_transfer_1.agentTransfer)(client, input)));
277
320
  registerTool(server, "shield_execute_swap", "Execute a Jupiter token swap through an AgentShield vault", {
278
321
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
279
322
  inputMint: zod_1.z.string().describe("Input token mint address (base58)"),
@@ -284,11 +327,7 @@ async function main() {
284
327
  .optional()
285
328
  .default(50)
286
329
  .describe("Slippage tolerance in BPS (default: 50)"),
287
- }, async (input) => ({
288
- content: [
289
- { type: "text", text: await (0, execute_swap_1.executeSwap)(client, config, input) },
290
- ],
291
- }));
330
+ }, requireClient((input) => (0, execute_swap_1.executeSwap)(client, config, input)));
292
331
  registerTool(server, "shield_open_position", "Open a leveraged perpetual position via Flash Trade through a vault", {
293
332
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
294
333
  market: zod_1.z.string().describe("Market/pool name (e.g. 'SOL', 'ETH')"),
@@ -303,11 +342,7 @@ async function main() {
303
342
  leverageBps: zod_1.z
304
343
  .number()
305
344
  .describe("Leverage in basis points (e.g. 20000 = 2x)"),
306
- }, async (input) => ({
307
- content: [
308
- { type: "text", text: await (0, open_position_1.openPosition)(client, config, input) },
309
- ],
310
- }));
345
+ }, requireClient((input) => (0, open_position_1.openPosition)(client, config, input)));
311
346
  registerTool(server, "shield_close_position", "Close a leveraged perpetual position via Flash Trade through a vault", {
312
347
  vault: zod_1.z.string().describe("Vault PDA address (base58)"),
313
348
  market: zod_1.z.string().describe("Market/pool name (e.g. 'SOL', 'ETH')"),
@@ -318,11 +353,7 @@ async function main() {
318
353
  .optional()
319
354
  .default(0)
320
355
  .describe("Price exponent (default: 0)"),
321
- }, async (input) => ({
322
- content: [
323
- { type: "text", text: await (0, close_position_1.closePosition)(client, config, input) },
324
- ],
325
- }));
356
+ }, requireClient((input) => (0, close_position_1.closePosition)(client, config, input)));
326
357
  // ── Platform Tools ─────────────────────────────────────────
327
358
  registerTool(server, "shield_provision", "Generate a Solana Action URL (Blink) for one-click vault provisioning. The user clicks the link to approve — no agent signing needed.", {
328
359
  platformUrl: zod_1.z
@@ -356,6 +387,17 @@ async function main() {
356
387
  }));
357
388
  // ── MCP Resources ───────────────────────────────────────────
358
389
  server.resource("vault-policy", "shield://vault/{address}/policy", { description: "Current policy configuration for a vault" }, async (uri) => {
390
+ if (!client) {
391
+ return {
392
+ contents: [
393
+ {
394
+ uri: uri.href,
395
+ mimeType: "text/plain",
396
+ text: NOT_CONFIGURED_MSG,
397
+ },
398
+ ],
399
+ };
400
+ }
359
401
  const address = uri.pathname.split("/")[2];
360
402
  return {
361
403
  contents: [
@@ -368,6 +410,17 @@ async function main() {
368
410
  };
369
411
  });
370
412
  server.resource("vault-spending", "shield://vault/{address}/spending", { description: "Rolling 24h spending state for a vault" }, async (uri) => {
413
+ if (!client) {
414
+ return {
415
+ contents: [
416
+ {
417
+ uri: uri.href,
418
+ mimeType: "text/plain",
419
+ text: NOT_CONFIGURED_MSG,
420
+ },
421
+ ],
422
+ };
423
+ }
371
424
  const address = uri.pathname.split("/")[2];
372
425
  return {
373
426
  contents: [
@@ -380,6 +433,17 @@ async function main() {
380
433
  };
381
434
  });
382
435
  server.resource("vault-activity", "shield://vault/{address}/activity", { description: "Recent transaction history for a vault" }, async (uri) => {
436
+ if (!client) {
437
+ return {
438
+ contents: [
439
+ {
440
+ uri: uri.href,
441
+ mimeType: "text/plain",
442
+ text: NOT_CONFIGURED_MSG,
443
+ },
444
+ ],
445
+ };
446
+ }
383
447
  const address = uri.pathname.split("/")[2];
384
448
  return {
385
449
  contents: [